@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 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
- ...options
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 response = await fetch(`${this.apiUrl}/a2a`, {
214
- method: "POST",
215
- headers: {
216
- "Content-Type": "application/json",
217
- "Authorization": `Bearer ${this.apiKey}`
218
- },
219
- body: JSON.stringify({
220
- jsonrpc: "2.0",
221
- method,
222
- params,
223
- id: Date.now()
224
- })
225
- });
226
- const data = await response.json();
227
- if (data.error) {
228
- throw new Error(data.error.message || "RPC error");
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
- ...options
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 response = await fetch(`${this.apiUrl}/a2a`, {
195
- method: "POST",
196
- headers: {
197
- "Content-Type": "application/json",
198
- "Authorization": `Bearer ${this.apiKey}`
199
- },
200
- body: JSON.stringify({
201
- jsonrpc: "2.0",
202
- method,
203
- params,
204
- id: Date.now()
205
- })
206
- });
207
- const data = await response.json();
208
- if (data.error) {
209
- throw new Error(data.error.message || "RPC error");
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gopherhole/sdk",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "GopherHole SDK - Connect AI agents via the A2A protocol",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
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
- ...options,
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>): Promise<unknown> {
309
- const response = await fetch(`${this.apiUrl}/a2a`, {
310
- method: 'POST',
311
- headers: {
312
- 'Content-Type': 'application/json',
313
- 'Authorization': `Bearer ${this.apiKey}`,
314
- },
315
- body: JSON.stringify({
316
- jsonrpc: '2.0',
317
- method,
318
- params,
319
- id: Date.now(),
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
- const data = await response.json();
375
+ const data = await response.json();
324
376
 
325
- if (data.error) {
326
- throw new Error(data.error.message || 'RPC error');
327
- }
377
+ if (data.error) {
378
+ throw new Error(data.error.message || 'RPC error');
379
+ }
328
380
 
329
- return data.result;
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
  /**