@gopherhole/sdk 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +21 -1
- package/dist/index.d.ts +21 -1
- package/dist/index.js +59 -20
- package/dist/index.mjs +59 -20
- package/package.json +1 -1
- package/src/index.ts +81 -21
package/dist/index.d.mts
CHANGED
|
@@ -192,6 +192,8 @@ interface GopherHoleOptions {
|
|
|
192
192
|
reconnectDelay?: number;
|
|
193
193
|
/** Max reconnect attempts */
|
|
194
194
|
maxReconnectAttempts?: number;
|
|
195
|
+
/** Default request timeout in ms (default: 30000) */
|
|
196
|
+
requestTimeout?: number;
|
|
195
197
|
}
|
|
196
198
|
/** Agent card configuration for registration */
|
|
197
199
|
interface AgentCardConfig {
|
|
@@ -253,6 +255,14 @@ interface SendOptions {
|
|
|
253
255
|
pushNotificationUrl?: string;
|
|
254
256
|
/** History length to include */
|
|
255
257
|
historyLength?: number;
|
|
258
|
+
/** Request timeout in ms (overrides default) */
|
|
259
|
+
timeoutMs?: number;
|
|
260
|
+
}
|
|
261
|
+
interface SendAndWaitOptions extends SendOptions {
|
|
262
|
+
/** Polling interval in ms (default: 1000) */
|
|
263
|
+
pollIntervalMs?: number;
|
|
264
|
+
/** Max wait time in ms (default: 300000 = 5 min) */
|
|
265
|
+
maxWaitMs?: number;
|
|
256
266
|
}
|
|
257
267
|
type EventMap = {
|
|
258
268
|
connect: () => void;
|
|
@@ -269,6 +279,7 @@ declare class GopherHole extends EventEmitter<EventMap> {
|
|
|
269
279
|
private autoReconnect;
|
|
270
280
|
private reconnectDelay;
|
|
271
281
|
private maxReconnectAttempts;
|
|
282
|
+
private requestTimeout;
|
|
272
283
|
private reconnectAttempts;
|
|
273
284
|
private reconnectTimer;
|
|
274
285
|
private pingInterval;
|
|
@@ -295,6 +306,15 @@ declare class GopherHole extends EventEmitter<EventMap> {
|
|
|
295
306
|
* Send a text message to another agent
|
|
296
307
|
*/
|
|
297
308
|
sendText(toAgentId: string, text: string, options?: SendOptions): Promise<Task>;
|
|
309
|
+
/**
|
|
310
|
+
* Send a text message and wait for completion
|
|
311
|
+
* Returns the completed task with response artifacts
|
|
312
|
+
*/
|
|
313
|
+
sendTextAndWait(toAgentId: string, text: string, options?: SendAndWaitOptions): Promise<Task>;
|
|
314
|
+
/**
|
|
315
|
+
* Wait for a task to complete (polling)
|
|
316
|
+
*/
|
|
317
|
+
waitForTask(taskId: string, options?: SendAndWaitOptions): Promise<Task>;
|
|
298
318
|
/**
|
|
299
319
|
* Get a task by ID
|
|
300
320
|
*/
|
|
@@ -502,4 +522,4 @@ interface RatingResult {
|
|
|
502
522
|
ratingCount: number;
|
|
503
523
|
}
|
|
504
524
|
|
|
505
|
-
export { type A2AArtifact, type A2AMessage, type A2ATask, type A2ATaskStatus, type AgentAuthentication, type AgentCapabilities, type AgentCard, type AgentCardConfig, type AgentCategory, type AgentInfoResult, type AgentReview, type AgentSkill, type AgentSkillConfig, type Artifact, type ContentMode, type DataContent, type DataPart, type DiscoverOptions, type DiscoverResult, type FileContent, type FilePart, GopherHole, type GopherHoleOptions, type InputMode, type JsonRpcError, JsonRpcErrorCodes, type JsonRpcRequest, type JsonRpcResponse, type Message, type MessagePart, type MessagePayload, type MessageSendConfiguration, type OutputMode, type Part, type PublicAgent, type PushNotificationConfig, type RatingResult, type SendOptions, type Task, type TaskArtifactUpdateEvent, type TaskEvent, type TaskListConfiguration, type TaskPushNotificationConfig, type TaskQueryConfiguration, type TaskState, type TaskStatus, type TaskStatusUpdateEvent, type TextPart, GopherHole as default };
|
|
525
|
+
export { type A2AArtifact, type A2AMessage, type A2ATask, type A2ATaskStatus, type AgentAuthentication, type AgentCapabilities, type AgentCard, type AgentCardConfig, type AgentCategory, type AgentInfoResult, type AgentReview, type AgentSkill, type AgentSkillConfig, type Artifact, type ContentMode, type DataContent, type DataPart, type DiscoverOptions, type DiscoverResult, type FileContent, type FilePart, GopherHole, type GopherHoleOptions, type InputMode, type JsonRpcError, JsonRpcErrorCodes, type JsonRpcRequest, type JsonRpcResponse, type Message, type MessagePart, type MessagePayload, type MessageSendConfiguration, type OutputMode, type Part, type PublicAgent, type PushNotificationConfig, type RatingResult, type SendAndWaitOptions, type SendOptions, type Task, type TaskArtifactUpdateEvent, type TaskEvent, type TaskListConfiguration, type TaskPushNotificationConfig, type TaskQueryConfiguration, type TaskState, type TaskStatus, type TaskStatusUpdateEvent, type TextPart, GopherHole as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -192,6 +192,8 @@ interface GopherHoleOptions {
|
|
|
192
192
|
reconnectDelay?: number;
|
|
193
193
|
/** Max reconnect attempts */
|
|
194
194
|
maxReconnectAttempts?: number;
|
|
195
|
+
/** Default request timeout in ms (default: 30000) */
|
|
196
|
+
requestTimeout?: number;
|
|
195
197
|
}
|
|
196
198
|
/** Agent card configuration for registration */
|
|
197
199
|
interface AgentCardConfig {
|
|
@@ -253,6 +255,14 @@ interface SendOptions {
|
|
|
253
255
|
pushNotificationUrl?: string;
|
|
254
256
|
/** History length to include */
|
|
255
257
|
historyLength?: number;
|
|
258
|
+
/** Request timeout in ms (overrides default) */
|
|
259
|
+
timeoutMs?: number;
|
|
260
|
+
}
|
|
261
|
+
interface SendAndWaitOptions extends SendOptions {
|
|
262
|
+
/** Polling interval in ms (default: 1000) */
|
|
263
|
+
pollIntervalMs?: number;
|
|
264
|
+
/** Max wait time in ms (default: 300000 = 5 min) */
|
|
265
|
+
maxWaitMs?: number;
|
|
256
266
|
}
|
|
257
267
|
type EventMap = {
|
|
258
268
|
connect: () => void;
|
|
@@ -269,6 +279,7 @@ declare class GopherHole extends EventEmitter<EventMap> {
|
|
|
269
279
|
private autoReconnect;
|
|
270
280
|
private reconnectDelay;
|
|
271
281
|
private maxReconnectAttempts;
|
|
282
|
+
private requestTimeout;
|
|
272
283
|
private reconnectAttempts;
|
|
273
284
|
private reconnectTimer;
|
|
274
285
|
private pingInterval;
|
|
@@ -295,6 +306,15 @@ declare class GopherHole extends EventEmitter<EventMap> {
|
|
|
295
306
|
* Send a text message to another agent
|
|
296
307
|
*/
|
|
297
308
|
sendText(toAgentId: string, text: string, options?: SendOptions): Promise<Task>;
|
|
309
|
+
/**
|
|
310
|
+
* Send a text message and wait for completion
|
|
311
|
+
* Returns the completed task with response artifacts
|
|
312
|
+
*/
|
|
313
|
+
sendTextAndWait(toAgentId: string, text: string, options?: SendAndWaitOptions): Promise<Task>;
|
|
314
|
+
/**
|
|
315
|
+
* Wait for a task to complete (polling)
|
|
316
|
+
*/
|
|
317
|
+
waitForTask(taskId: string, options?: SendAndWaitOptions): Promise<Task>;
|
|
298
318
|
/**
|
|
299
319
|
* Get a task by ID
|
|
300
320
|
*/
|
|
@@ -502,4 +522,4 @@ interface RatingResult {
|
|
|
502
522
|
ratingCount: number;
|
|
503
523
|
}
|
|
504
524
|
|
|
505
|
-
export { type A2AArtifact, type A2AMessage, type A2ATask, type A2ATaskStatus, type AgentAuthentication, type AgentCapabilities, type AgentCard, type AgentCardConfig, type AgentCategory, type AgentInfoResult, type AgentReview, type AgentSkill, type AgentSkillConfig, type Artifact, type ContentMode, type DataContent, type DataPart, type DiscoverOptions, type DiscoverResult, type FileContent, type FilePart, GopherHole, type GopherHoleOptions, type InputMode, type JsonRpcError, JsonRpcErrorCodes, type JsonRpcRequest, type JsonRpcResponse, type Message, type MessagePart, type MessagePayload, type MessageSendConfiguration, type OutputMode, type Part, type PublicAgent, type PushNotificationConfig, type RatingResult, type SendOptions, type Task, type TaskArtifactUpdateEvent, type TaskEvent, type TaskListConfiguration, type TaskPushNotificationConfig, type TaskQueryConfiguration, type TaskState, type TaskStatus, type TaskStatusUpdateEvent, type TextPart, GopherHole as default };
|
|
525
|
+
export { type A2AArtifact, type A2AMessage, type A2ATask, type A2ATaskStatus, type AgentAuthentication, type AgentCapabilities, type AgentCard, type AgentCardConfig, type AgentCategory, type AgentInfoResult, type AgentReview, type AgentSkill, type AgentSkillConfig, type Artifact, type ContentMode, type DataContent, type DataPart, type DiscoverOptions, type DiscoverResult, type FileContent, type FilePart, GopherHole, type GopherHoleOptions, type InputMode, type JsonRpcError, JsonRpcErrorCodes, type JsonRpcRequest, type JsonRpcResponse, type Message, type MessagePart, type MessagePayload, type MessageSendConfiguration, type OutputMode, type Part, type PublicAgent, type PushNotificationConfig, type RatingResult, type SendAndWaitOptions, type SendOptions, type Task, type TaskArtifactUpdateEvent, type TaskEvent, type TaskListConfiguration, type TaskPushNotificationConfig, type TaskQueryConfiguration, type TaskState, type TaskStatus, type TaskStatusUpdateEvent, type TextPart, GopherHole as default };
|
package/dist/index.js
CHANGED
|
@@ -62,6 +62,7 @@ var GopherHole = class extends import_eventemitter3.EventEmitter {
|
|
|
62
62
|
this.autoReconnect = options.autoReconnect ?? true;
|
|
63
63
|
this.reconnectDelay = options.reconnectDelay ?? 1e3;
|
|
64
64
|
this.maxReconnectAttempts = options.maxReconnectAttempts ?? 10;
|
|
65
|
+
this.requestTimeout = options.requestTimeout ?? 3e4;
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
68
|
* Update agent card (sends to hub if connected)
|
|
@@ -132,13 +133,14 @@ var GopherHole = class extends import_eventemitter3.EventEmitter {
|
|
|
132
133
|
* Send a message to another agent
|
|
133
134
|
*/
|
|
134
135
|
async send(toAgentId, payload, options) {
|
|
136
|
+
const { timeoutMs, ...config } = options || {};
|
|
135
137
|
const response = await this.rpc("message/send", {
|
|
136
138
|
message: payload,
|
|
137
139
|
configuration: {
|
|
138
140
|
agentId: toAgentId,
|
|
139
|
-
...
|
|
141
|
+
...config
|
|
140
142
|
}
|
|
141
|
-
});
|
|
143
|
+
}, timeoutMs);
|
|
142
144
|
return response;
|
|
143
145
|
}
|
|
144
146
|
/**
|
|
@@ -150,6 +152,30 @@ var GopherHole = class extends import_eventemitter3.EventEmitter {
|
|
|
150
152
|
parts: [{ kind: "text", text }]
|
|
151
153
|
}, options);
|
|
152
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Send a text message and wait for completion
|
|
157
|
+
* Returns the completed task with response artifacts
|
|
158
|
+
*/
|
|
159
|
+
async sendTextAndWait(toAgentId, text, options) {
|
|
160
|
+
const task = await this.sendText(toAgentId, text, options);
|
|
161
|
+
return this.waitForTask(task.id, options);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Wait for a task to complete (polling)
|
|
165
|
+
*/
|
|
166
|
+
async waitForTask(taskId, options) {
|
|
167
|
+
const pollInterval = options?.pollIntervalMs ?? 1e3;
|
|
168
|
+
const maxWait = options?.maxWaitMs ?? 3e5;
|
|
169
|
+
const startTime = Date.now();
|
|
170
|
+
while (Date.now() - startTime < maxWait) {
|
|
171
|
+
const task = await this.getTask(taskId);
|
|
172
|
+
if (task.status.state === "completed" || task.status.state === "failed" || task.status.state === "canceled" || task.status.state === "rejected") {
|
|
173
|
+
return task;
|
|
174
|
+
}
|
|
175
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
176
|
+
}
|
|
177
|
+
throw new Error(`Task ${taskId} did not complete within ${maxWait}ms`);
|
|
178
|
+
}
|
|
153
179
|
/**
|
|
154
180
|
* Get a task by ID
|
|
155
181
|
*/
|
|
@@ -209,25 +235,38 @@ var GopherHole = class extends import_eventemitter3.EventEmitter {
|
|
|
209
235
|
/**
|
|
210
236
|
* Make a JSON-RPC call to the A2A endpoint
|
|
211
237
|
*/
|
|
212
|
-
async rpc(method, params) {
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
238
|
+
async rpc(method, params, timeoutMs) {
|
|
239
|
+
const timeout = timeoutMs ?? this.requestTimeout;
|
|
240
|
+
const controller = new AbortController();
|
|
241
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
242
|
+
try {
|
|
243
|
+
const response = await fetch(`${this.apiUrl}/a2a`, {
|
|
244
|
+
method: "POST",
|
|
245
|
+
headers: {
|
|
246
|
+
"Content-Type": "application/json",
|
|
247
|
+
"Authorization": `Bearer ${this.apiKey}`
|
|
248
|
+
},
|
|
249
|
+
body: JSON.stringify({
|
|
250
|
+
jsonrpc: "2.0",
|
|
251
|
+
method,
|
|
252
|
+
params,
|
|
253
|
+
id: Date.now()
|
|
254
|
+
}),
|
|
255
|
+
signal: controller.signal
|
|
256
|
+
});
|
|
257
|
+
const data = await response.json();
|
|
258
|
+
if (data.error) {
|
|
259
|
+
throw new Error(data.error.message || "RPC error");
|
|
260
|
+
}
|
|
261
|
+
return data.result;
|
|
262
|
+
} catch (err) {
|
|
263
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
264
|
+
throw new Error(`Request timeout after ${timeout}ms`);
|
|
265
|
+
}
|
|
266
|
+
throw err;
|
|
267
|
+
} finally {
|
|
268
|
+
clearTimeout(timeoutId);
|
|
229
269
|
}
|
|
230
|
-
return data.result;
|
|
231
270
|
}
|
|
232
271
|
/**
|
|
233
272
|
* Handle incoming WebSocket messages
|
package/dist/index.mjs
CHANGED
|
@@ -43,6 +43,7 @@ var GopherHole = class extends EventEmitter {
|
|
|
43
43
|
this.autoReconnect = options.autoReconnect ?? true;
|
|
44
44
|
this.reconnectDelay = options.reconnectDelay ?? 1e3;
|
|
45
45
|
this.maxReconnectAttempts = options.maxReconnectAttempts ?? 10;
|
|
46
|
+
this.requestTimeout = options.requestTimeout ?? 3e4;
|
|
46
47
|
}
|
|
47
48
|
/**
|
|
48
49
|
* Update agent card (sends to hub if connected)
|
|
@@ -113,13 +114,14 @@ var GopherHole = class extends EventEmitter {
|
|
|
113
114
|
* Send a message to another agent
|
|
114
115
|
*/
|
|
115
116
|
async send(toAgentId, payload, options) {
|
|
117
|
+
const { timeoutMs, ...config } = options || {};
|
|
116
118
|
const response = await this.rpc("message/send", {
|
|
117
119
|
message: payload,
|
|
118
120
|
configuration: {
|
|
119
121
|
agentId: toAgentId,
|
|
120
|
-
...
|
|
122
|
+
...config
|
|
121
123
|
}
|
|
122
|
-
});
|
|
124
|
+
}, timeoutMs);
|
|
123
125
|
return response;
|
|
124
126
|
}
|
|
125
127
|
/**
|
|
@@ -131,6 +133,30 @@ var GopherHole = class extends EventEmitter {
|
|
|
131
133
|
parts: [{ kind: "text", text }]
|
|
132
134
|
}, options);
|
|
133
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Send a text message and wait for completion
|
|
138
|
+
* Returns the completed task with response artifacts
|
|
139
|
+
*/
|
|
140
|
+
async sendTextAndWait(toAgentId, text, options) {
|
|
141
|
+
const task = await this.sendText(toAgentId, text, options);
|
|
142
|
+
return this.waitForTask(task.id, options);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Wait for a task to complete (polling)
|
|
146
|
+
*/
|
|
147
|
+
async waitForTask(taskId, options) {
|
|
148
|
+
const pollInterval = options?.pollIntervalMs ?? 1e3;
|
|
149
|
+
const maxWait = options?.maxWaitMs ?? 3e5;
|
|
150
|
+
const startTime = Date.now();
|
|
151
|
+
while (Date.now() - startTime < maxWait) {
|
|
152
|
+
const task = await this.getTask(taskId);
|
|
153
|
+
if (task.status.state === "completed" || task.status.state === "failed" || task.status.state === "canceled" || task.status.state === "rejected") {
|
|
154
|
+
return task;
|
|
155
|
+
}
|
|
156
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
157
|
+
}
|
|
158
|
+
throw new Error(`Task ${taskId} did not complete within ${maxWait}ms`);
|
|
159
|
+
}
|
|
134
160
|
/**
|
|
135
161
|
* Get a task by ID
|
|
136
162
|
*/
|
|
@@ -190,25 +216,38 @@ var GopherHole = class extends EventEmitter {
|
|
|
190
216
|
/**
|
|
191
217
|
* Make a JSON-RPC call to the A2A endpoint
|
|
192
218
|
*/
|
|
193
|
-
async rpc(method, params) {
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
219
|
+
async rpc(method, params, timeoutMs) {
|
|
220
|
+
const timeout = timeoutMs ?? this.requestTimeout;
|
|
221
|
+
const controller = new AbortController();
|
|
222
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
223
|
+
try {
|
|
224
|
+
const response = await fetch(`${this.apiUrl}/a2a`, {
|
|
225
|
+
method: "POST",
|
|
226
|
+
headers: {
|
|
227
|
+
"Content-Type": "application/json",
|
|
228
|
+
"Authorization": `Bearer ${this.apiKey}`
|
|
229
|
+
},
|
|
230
|
+
body: JSON.stringify({
|
|
231
|
+
jsonrpc: "2.0",
|
|
232
|
+
method,
|
|
233
|
+
params,
|
|
234
|
+
id: Date.now()
|
|
235
|
+
}),
|
|
236
|
+
signal: controller.signal
|
|
237
|
+
});
|
|
238
|
+
const data = await response.json();
|
|
239
|
+
if (data.error) {
|
|
240
|
+
throw new Error(data.error.message || "RPC error");
|
|
241
|
+
}
|
|
242
|
+
return data.result;
|
|
243
|
+
} catch (err) {
|
|
244
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
245
|
+
throw new Error(`Request timeout after ${timeout}ms`);
|
|
246
|
+
}
|
|
247
|
+
throw err;
|
|
248
|
+
} finally {
|
|
249
|
+
clearTimeout(timeoutId);
|
|
210
250
|
}
|
|
211
|
-
return data.result;
|
|
212
251
|
}
|
|
213
252
|
/**
|
|
214
253
|
* Handle incoming WebSocket messages
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -16,6 +16,8 @@ export interface GopherHoleOptions {
|
|
|
16
16
|
reconnectDelay?: number;
|
|
17
17
|
/** Max reconnect attempts */
|
|
18
18
|
maxReconnectAttempts?: number;
|
|
19
|
+
/** Default request timeout in ms (default: 30000) */
|
|
20
|
+
requestTimeout?: number;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
/** Agent card configuration for registration */
|
|
@@ -86,6 +88,15 @@ export interface SendOptions {
|
|
|
86
88
|
pushNotificationUrl?: string;
|
|
87
89
|
/** History length to include */
|
|
88
90
|
historyLength?: number;
|
|
91
|
+
/** Request timeout in ms (overrides default) */
|
|
92
|
+
timeoutMs?: number;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface SendAndWaitOptions extends SendOptions {
|
|
96
|
+
/** Polling interval in ms (default: 1000) */
|
|
97
|
+
pollIntervalMs?: number;
|
|
98
|
+
/** Max wait time in ms (default: 300000 = 5 min) */
|
|
99
|
+
maxWaitMs?: number;
|
|
89
100
|
}
|
|
90
101
|
|
|
91
102
|
type EventMap = {
|
|
@@ -107,6 +118,7 @@ export class GopherHole extends EventEmitter<EventMap> {
|
|
|
107
118
|
private autoReconnect: boolean;
|
|
108
119
|
private reconnectDelay: number;
|
|
109
120
|
private maxReconnectAttempts: number;
|
|
121
|
+
private requestTimeout: number;
|
|
110
122
|
private reconnectAttempts = 0;
|
|
111
123
|
private reconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
|
112
124
|
private pingInterval: ReturnType<typeof setInterval> | null = null;
|
|
@@ -127,6 +139,7 @@ export class GopherHole extends EventEmitter<EventMap> {
|
|
|
127
139
|
this.autoReconnect = options.autoReconnect ?? true;
|
|
128
140
|
this.reconnectDelay = options.reconnectDelay ?? 1000;
|
|
129
141
|
this.maxReconnectAttempts = options.maxReconnectAttempts ?? 10;
|
|
142
|
+
this.requestTimeout = options.requestTimeout ?? 30000;
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
/**
|
|
@@ -209,13 +222,14 @@ export class GopherHole extends EventEmitter<EventMap> {
|
|
|
209
222
|
* Send a message to another agent
|
|
210
223
|
*/
|
|
211
224
|
async send(toAgentId: string, payload: MessagePayload, options?: SendOptions): Promise<Task> {
|
|
225
|
+
const { timeoutMs, ...config } = options || {};
|
|
212
226
|
const response = await this.rpc('message/send', {
|
|
213
227
|
message: payload,
|
|
214
228
|
configuration: {
|
|
215
229
|
agentId: toAgentId,
|
|
216
|
-
...
|
|
230
|
+
...config,
|
|
217
231
|
},
|
|
218
|
-
});
|
|
232
|
+
}, timeoutMs);
|
|
219
233
|
|
|
220
234
|
return response as Task;
|
|
221
235
|
}
|
|
@@ -230,6 +244,38 @@ export class GopherHole extends EventEmitter<EventMap> {
|
|
|
230
244
|
}, options);
|
|
231
245
|
}
|
|
232
246
|
|
|
247
|
+
/**
|
|
248
|
+
* Send a text message and wait for completion
|
|
249
|
+
* Returns the completed task with response artifacts
|
|
250
|
+
*/
|
|
251
|
+
async sendTextAndWait(toAgentId: string, text: string, options?: SendAndWaitOptions): Promise<Task> {
|
|
252
|
+
const task = await this.sendText(toAgentId, text, options);
|
|
253
|
+
return this.waitForTask(task.id, options);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Wait for a task to complete (polling)
|
|
258
|
+
*/
|
|
259
|
+
async waitForTask(taskId: string, options?: SendAndWaitOptions): Promise<Task> {
|
|
260
|
+
const pollInterval = options?.pollIntervalMs ?? 1000;
|
|
261
|
+
const maxWait = options?.maxWaitMs ?? 300000; // 5 min default
|
|
262
|
+
const startTime = Date.now();
|
|
263
|
+
|
|
264
|
+
while (Date.now() - startTime < maxWait) {
|
|
265
|
+
const task = await this.getTask(taskId);
|
|
266
|
+
|
|
267
|
+
if (task.status.state === 'completed' || task.status.state === 'failed' ||
|
|
268
|
+
task.status.state === 'canceled' || task.status.state === 'rejected') {
|
|
269
|
+
return task;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Wait before polling again
|
|
273
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
throw new Error(`Task ${taskId} did not complete within ${maxWait}ms`);
|
|
277
|
+
}
|
|
278
|
+
|
|
233
279
|
/**
|
|
234
280
|
* Get a task by ID
|
|
235
281
|
*/
|
|
@@ -305,28 +351,42 @@ export class GopherHole extends EventEmitter<EventMap> {
|
|
|
305
351
|
/**
|
|
306
352
|
* Make a JSON-RPC call to the A2A endpoint
|
|
307
353
|
*/
|
|
308
|
-
private async rpc(method: string, params: Record<string, unknown
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
354
|
+
private async rpc(method: string, params: Record<string, unknown>, timeoutMs?: number): Promise<unknown> {
|
|
355
|
+
const timeout = timeoutMs ?? this.requestTimeout;
|
|
356
|
+
const controller = new AbortController();
|
|
357
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
const response = await fetch(`${this.apiUrl}/a2a`, {
|
|
361
|
+
method: 'POST',
|
|
362
|
+
headers: {
|
|
363
|
+
'Content-Type': 'application/json',
|
|
364
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
365
|
+
},
|
|
366
|
+
body: JSON.stringify({
|
|
367
|
+
jsonrpc: '2.0',
|
|
368
|
+
method,
|
|
369
|
+
params,
|
|
370
|
+
id: Date.now(),
|
|
371
|
+
}),
|
|
372
|
+
signal: controller.signal,
|
|
373
|
+
});
|
|
322
374
|
|
|
323
|
-
|
|
375
|
+
const data = await response.json();
|
|
324
376
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
377
|
+
if (data.error) {
|
|
378
|
+
throw new Error(data.error.message || 'RPC error');
|
|
379
|
+
}
|
|
328
380
|
|
|
329
|
-
|
|
381
|
+
return data.result;
|
|
382
|
+
} catch (err) {
|
|
383
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
384
|
+
throw new Error(`Request timeout after ${timeout}ms`);
|
|
385
|
+
}
|
|
386
|
+
throw err;
|
|
387
|
+
} finally {
|
|
388
|
+
clearTimeout(timeoutId);
|
|
389
|
+
}
|
|
330
390
|
}
|
|
331
391
|
|
|
332
392
|
/**
|