-
Notifications
You must be signed in to change notification settings - Fork 136
Expand file tree
/
Copy pathinterceptors.ts
More file actions
134 lines (119 loc) · 3.47 KB
/
interceptors.ts
File metadata and controls
134 lines (119 loc) · 3.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import { AgentCard } from '../types.js';
import { A2AStreamEventData } from './client.js';
import { Client } from './multitransport-client.js';
import { RequestOptions } from './multitransport-client.js';
export interface CallInterceptor {
/**
* Invoked before transport method.
*/
before(args: BeforeArgs): Promise<void>;
/**
* Invoked after transport method.
*/
after(args: AfterArgs): Promise<void>;
}
export interface BeforeArgs<K extends keyof Client = keyof Client> {
/**
* Identifies the client method invoked and its payload.
* Payload inside the input object can be modified.
*/
readonly input: ClientCallInput<K>;
/**
* Identifies the agent card cached on the client
*/
readonly agentCard: AgentCard;
/**
* If set by the interceptor, stops execution, invokes "after"
* for executed interceptors and returns the result. Transport is not called.
*/
earlyReturn?: ClientCallResult<K>;
/**
* Options passed to the client.
*/
options?: RequestOptions;
}
export interface AfterArgs<K extends keyof Client = keyof Client> {
/**
* Identifies the client method invoked and its result.
* Payload inside the result object can be modified.
*/
readonly result: ClientCallResult<K>;
/**
* Identifies the agent card cached on the client
*/
readonly agentCard: AgentCard;
/**
* If set by the interceptor, stops execution and returns result value,
* remaining interceptors are not executed.
*/
earlyReturn?: boolean;
/**
* Options passed to the client.
*/
options?: RequestOptions;
}
export type ClientCallInput<K extends keyof Client = keyof Client> = MethodInput<Client, K>;
export type ClientCallResult<K extends keyof Client = keyof Client> = MethodResult<
Client,
K,
ResultsOverrides
>;
// Types below are helper types and are not exported to allow simplifying it without affecting
// public API if necessary. They are exported via type aliases ClientXxx which can be replaced with explicit union if necessary.
/**
* For
*
* interface Foo {
* f1(arg: string): Promise<Result1>;
* f2(arg: number): Promise<Result2>;
* }
*
* MethodInputs<Foo> resolves to
*
* {
* readonly method: "f1";
* value: string;
* } | {
* readonly method: "f2";
* value: number;
* }
*/
type MethodInput<T, TMembers extends keyof T = keyof T> = {
[M in TMembers]: T[M] extends (options: RequestOptions | undefined) => unknown
? { readonly method: M; value?: never }
: T[M] extends (payload: infer P) => unknown
? { readonly method: M; value: P }
: never;
}[TMembers];
/**
* For
*
* interface Foo {
* f1(): Promise<Result1>;
* f2(): Promise<Result2>;
* }
*
* MethodsResults<Foo> resolves to
*
* {
* readonly method: "f1";
* value: Result1;
* } | {
* readonly method: "f2";
* value: Result2;
* }
*/
type MethodResult<T, TMembers extends keyof T = keyof T, TOverrides = object> = {
[M in TMembers]: M extends keyof TOverrides // If there is an override, use it directly.
? { readonly method: M; value: TOverrides[M] }
: // Infer result, unwrap it from Promise and pack with method name.
T[M] extends (payload: unknown) => infer R
? { readonly method: M; value: Awaited<R> }
: never;
}[TMembers];
interface ResultsOverrides {
// sendMessageStream and resubscribeTask return async iterators and are intercepted on each item,
// which requires custom handling.
sendMessageStream: A2AStreamEventData;
resubscribeTask: A2AStreamEventData;
}