@rkat/mobkit-sdk 0.5.2 → 0.6.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.
Files changed (50) hide show
  1. package/dist/agent-builder.d.ts +13 -1
  2. package/dist/agent-builder.d.ts.map +1 -1
  3. package/dist/agent-builder.js +166 -1
  4. package/dist/agent-builder.js.map +1 -1
  5. package/dist/builder.d.ts +28 -0
  6. package/dist/builder.d.ts.map +1 -1
  7. package/dist/builder.js +57 -0
  8. package/dist/builder.js.map +1 -1
  9. package/dist/cjs/agent-builder.cjs +165 -0
  10. package/dist/cjs/builder.cjs +57 -0
  11. package/dist/cjs/errors.cjs +72 -2
  12. package/dist/cjs/events.cjs +15 -5
  13. package/dist/cjs/index.cjs +37 -2
  14. package/dist/cjs/models.cjs +2 -2
  15. package/dist/cjs/runtime.cjs +306 -16
  16. package/dist/cjs/sse.cjs +12 -8
  17. package/dist/cjs/transport.cjs +47 -17
  18. package/dist/cjs/types.cjs +483 -5
  19. package/dist/errors.d.ts +38 -1
  20. package/dist/errors.d.ts.map +1 -1
  21. package/dist/errors.js +68 -1
  22. package/dist/errors.js.map +1 -1
  23. package/dist/events.d.ts +7 -0
  24. package/dist/events.d.ts.map +1 -1
  25. package/dist/events.js +15 -5
  26. package/dist/events.js.map +1 -1
  27. package/dist/index.d.ts +3 -3
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +4 -2
  30. package/dist/index.js.map +1 -1
  31. package/dist/models.d.ts +2 -2
  32. package/dist/models.d.ts.map +1 -1
  33. package/dist/models.js +2 -2
  34. package/dist/models.js.map +1 -1
  35. package/dist/runtime.d.ts +93 -3
  36. package/dist/runtime.d.ts.map +1 -1
  37. package/dist/runtime.js +308 -18
  38. package/dist/runtime.js.map +1 -1
  39. package/dist/sse.d.ts.map +1 -1
  40. package/dist/sse.js +12 -8
  41. package/dist/sse.js.map +1 -1
  42. package/dist/transport.d.ts +13 -0
  43. package/dist/transport.d.ts.map +1 -1
  44. package/dist/transport.js +46 -16
  45. package/dist/transport.js.map +1 -1
  46. package/dist/types.d.ts +265 -4
  47. package/dist/types.d.ts.map +1 -1
  48. package/dist/types.js +454 -5
  49. package/dist/types.js.map +1 -1
  50. package/package.json +1 -1
@@ -30,6 +30,19 @@ let requestCounter = 0;
30
30
  function nextRequestId(method) {
31
31
  return `${method}:${++requestCounter}`;
32
32
  }
33
+ function extractMobStructuralEvents(raw) {
34
+ let events = raw;
35
+ if (typeof raw === "object" && raw !== null) {
36
+ const record = raw;
37
+ if (Array.isArray(record.events)) {
38
+ events = record.events;
39
+ }
40
+ }
41
+ if (!Array.isArray(events)) {
42
+ return [];
43
+ }
44
+ return events.map(types_js_1.parseMobStructuralEvent);
45
+ }
33
46
  /** Serialize a config value for JSON transport.
34
47
  *
35
48
  * Recursively walks dicts/arrays with cycle detection. Calls toDict()
@@ -112,11 +125,20 @@ class MobKitRuntime {
112
125
  this._rustHttpBase = String(initResult.http_base_url ?? "") || null;
113
126
  }
114
127
  }
115
- catch {
128
+ catch (err) {
129
+ // Pre-fix every error path here was rewritten to a generic
130
+ // `TransportError`, destroying the original RPC code/message
131
+ // (e.g. config errors like `bad mob.toml: line 7`). The fix:
132
+ // only synthesize TransportError when the subprocess actually
133
+ // died; otherwise re-throw the structured RpcError so operators
134
+ // can diagnose config errors without spelunking gateway logs.
116
135
  if (this._transport !== null && !this._transport.isRunning()) {
117
136
  throw new errors_js_1.TransportError("gateway process died during bootstrap");
118
137
  }
119
- throw new errors_js_1.TransportError("mobkit/init failed — runtime could not be initialized");
138
+ if ((0, errors_js_1.isRpcError)(err)) {
139
+ throw err;
140
+ }
141
+ throw new errors_js_1.TransportError(`mobkit/init failed: ${err instanceof Error ? err.message : String(err)}`);
120
142
  }
121
143
  }
122
144
  else if (this._config.sessionBuilder) {
@@ -157,6 +179,9 @@ class MobKitRuntime {
157
179
  runtimeOptions.event_log = serializeConfig(this._config.eventLog);
158
180
  }
159
181
  params.runtime_options = runtimeOptions;
182
+ if (this._config.persistentState) {
183
+ params.persistent_state = this._config.persistentState;
184
+ }
160
185
  return params;
161
186
  }
162
187
  /** @internal */
@@ -169,7 +194,7 @@ class MobKitRuntime {
169
194
  const response = (await this._transport.sendAsync(request));
170
195
  if ("error" in response) {
171
196
  const err = response.error;
172
- throw new errors_js_1.RpcError(Number(err.code ?? -1), String(err.message ?? String(err)), rid, method);
197
+ throw new errors_js_1.RpcError(Number(err.code ?? -1), String(err.message ?? String(err)), rid, method, err.data);
173
198
  }
174
199
  return response.result;
175
200
  }
@@ -195,6 +220,58 @@ class MobKitRuntime {
195
220
  get isRunning() {
196
221
  return this._running;
197
222
  }
223
+ // -- Identity-first APIs (REQ-47) -----------------------------------------
224
+ /** Get agent snapshot by identity. */
225
+ async agent(identity) {
226
+ return (0, types_js_1.parseMemberSnapshot)(await this._rpc("mobkit/identity/agent", { identity }));
227
+ }
228
+ /** Send content to an identity. Content can be a string or content blocks. */
229
+ async send(identity, content) {
230
+ const params = { identity };
231
+ if (typeof content === "string") {
232
+ params.content = content;
233
+ }
234
+ else {
235
+ params.content = content.map((b) => {
236
+ if (b.type === "image") {
237
+ return { type: "image", media_type: b.mediaType, data: b.data };
238
+ }
239
+ return { type: "text", text: b.text };
240
+ });
241
+ }
242
+ return this._rpc("mobkit/identity/send", params);
243
+ }
244
+ /** Dispatch structured input to an identity. */
245
+ async dispatch(identity, input) {
246
+ return this._rpc("mobkit/identity/dispatch", {
247
+ identity,
248
+ dispatch_input: (0, types_js_1.dispatchInputToDict)(input),
249
+ });
250
+ }
251
+ /** Subscribe to events for an identity. */
252
+ async subscribe(identity) {
253
+ return this._rpc("mobkit/identity/subscribe", { identity });
254
+ }
255
+ /** Get identity status. */
256
+ async status(identity) {
257
+ return (0, types_js_1.parseIdentityStatus)(await this._rpc("mobkit/identity/status", { identity }));
258
+ }
259
+ /** Respawn an identity (non-destructive recovery). */
260
+ async respawn(identity) {
261
+ return this._rpc("mobkit/identity/respawn", { identity });
262
+ }
263
+ /** Retire an identity. */
264
+ async retire(identity) {
265
+ return this._rpc("mobkit/identity/retire", { identity });
266
+ }
267
+ /** Reset an identity (destructive continuity reset). */
268
+ async reset(identity) {
269
+ return this._rpc("mobkit/identity/reset", { identity });
270
+ }
271
+ /** Delete an identity permanently. */
272
+ async deleteIdentity(identity) {
273
+ return this._rpc("mobkit/identity/delete", { identity });
274
+ }
198
275
  }
199
276
  exports.MobKitRuntime = MobKitRuntime;
200
277
  // -- MobHandle ------------------------------------------------------------
@@ -205,7 +282,7 @@ exports.MobKitRuntime = MobKitRuntime;
205
282
  * ```ts
206
283
  * const handle = runtime.mobHandle();
207
284
  * const members = await handle.listMembers();
208
- * await handle.send(members[0].meerkatId, "Hello!");
285
+ * await handle.send(members[0].agentIdentity, "Hello!");
209
286
  * ```
210
287
  */
211
288
  class MobHandle {
@@ -255,16 +332,66 @@ class MobHandle {
255
332
  async queryEvents(query) {
256
333
  const params = query ? (0, types_js_1.eventQueryToDict)(query) : {};
257
334
  const raw = await this._runtime._rpc("mobkit/query_events", params);
258
- if (typeof raw === "object" &&
259
- raw !== null &&
260
- raw.status === "no_event_log_configured") {
261
- return [];
335
+ let events = raw;
336
+ if (typeof raw === "object" && raw !== null) {
337
+ const record = raw;
338
+ if (record.status === "no_event_log_configured") {
339
+ events = Array.isArray(record.events) ? record.events : [];
340
+ }
262
341
  }
263
- if (Array.isArray(raw)) {
264
- return raw.map(types_js_1.parsePersistedEvent);
342
+ if (Array.isArray(events)) {
343
+ return events.map(types_js_1.parsePersistedEvent);
265
344
  }
266
345
  return [];
267
346
  }
347
+ /**
348
+ * Query structural mob events from the meerkat ledger. Pass the
349
+ * highest seen `cursor` as `EventQuery.afterSeq` on the next call to
350
+ * paginate. Without `afterSeq` the call returns the latest matching
351
+ * events (default `limit = 256`).
352
+ *
353
+ * Throws {@link MobEventsStaleError} when `afterSeq` is past the
354
+ * current ledger frontier; the exception carries `afterCursor` and
355
+ * `latestCursor` so callers can rewind.
356
+ */
357
+ async queryMobEvents(query) {
358
+ const params = query ? (0, types_js_1.eventQueryToDict)(query) : {};
359
+ try {
360
+ const raw = await this._runtime._rpc("mobkit/mob_events/query", params);
361
+ return extractMobStructuralEvents(raw);
362
+ }
363
+ catch (err) {
364
+ if ((0, errors_js_1.isRpcError)(err) && err.code === errors_js_1.MOB_EVENTS_STALE_CURSOR_CODE) {
365
+ throw errors_js_1.MobEventsStaleError.fromRpcError(err);
366
+ }
367
+ throw err;
368
+ }
369
+ }
370
+ /**
371
+ * Replay structural mob events as an async iterator. Yields the
372
+ * snapshot frame returned by `mobkit/mob_events/subscribe`. Live
373
+ * tailing for production streaming uses the SSE bridge at
374
+ * `/mobkit/mob_events/stream`.
375
+ *
376
+ * Throws {@link MobEventsStaleError} when `afterSeq` is past the
377
+ * current ledger frontier.
378
+ */
379
+ async *subscribeMobEvents(query) {
380
+ const params = query ? (0, types_js_1.eventQueryToDict)(query) : {};
381
+ let raw;
382
+ try {
383
+ raw = await this._runtime._rpc("mobkit/mob_events/subscribe", params);
384
+ }
385
+ catch (err) {
386
+ if ((0, errors_js_1.isRpcError)(err) && err.code === errors_js_1.MOB_EVENTS_STALE_CURSOR_CODE) {
387
+ throw errors_js_1.MobEventsStaleError.fromRpcError(err);
388
+ }
389
+ throw err;
390
+ }
391
+ for (const event of extractMobStructuralEvents(raw)) {
392
+ yield event;
393
+ }
394
+ }
268
395
  // -- Messaging ----------------------------------------------------------
269
396
  async send(memberId, message) {
270
397
  return (0, types_js_1.parseSendMessageResult)(await this._runtime._rpc("mobkit/send_message", {
@@ -274,10 +401,10 @@ class MobHandle {
274
401
  }
275
402
  /** Alias for {@link send}. */
276
403
  sendMessage = this.send.bind(this);
277
- async ensureMember(memberId, profile, options) {
404
+ async ensureMember(memberId, role, options) {
278
405
  const params = {
279
- profile,
280
- meerkat_id: memberId,
406
+ role,
407
+ agent_identity: memberId,
281
408
  };
282
409
  if (options?.labels)
283
410
  params.labels = options.labels;
@@ -322,6 +449,95 @@ class MobHandle {
322
449
  member_id: memberId,
323
450
  });
324
451
  }
452
+ /**
453
+ * Wait until all current mob members are startup-ready for orchestration.
454
+ *
455
+ * Relays meerkat 0.6's `MobHandle::wait_for_ready`. Returns
456
+ * `{ ready: [...], timeout: false }` on full convergence; on timeout
457
+ * returns `{ ready: [], timeout: true }`. Pass `timeoutSeconds` to bound
458
+ * the wait, or omit it to block indefinitely.
459
+ */
460
+ async waitReady(timeoutSeconds) {
461
+ const params = {};
462
+ if (timeoutSeconds !== undefined) {
463
+ params.timeout_ms = Math.round(timeoutSeconds * 1000);
464
+ }
465
+ const raw = await this._runtime._rpc("mobkit/wait_ready", params);
466
+ if (typeof raw !== "object" || raw === null) {
467
+ return { ready: [], timeout: false };
468
+ }
469
+ const r = raw;
470
+ return {
471
+ ready: Array.isArray(r.ready) ? r.ready : [],
472
+ timeout: Boolean(r.timeout),
473
+ };
474
+ }
475
+ // -- Flows --------------------------------------------------------------
476
+ /**
477
+ * List all configured flow IDs in this mob definition. Relays meerkat
478
+ * 0.6's `MobHandle::list_flows`. Order is unspecified.
479
+ */
480
+ async listFlows() {
481
+ const raw = await this._runtime._rpc("mobkit/list_flows");
482
+ if (Array.isArray(raw)) {
483
+ return raw.map((id) => String(id));
484
+ }
485
+ if (typeof raw === "object" && raw !== null) {
486
+ const flows = raw.flows;
487
+ if (Array.isArray(flows)) {
488
+ return flows.map((id) => String(id));
489
+ }
490
+ }
491
+ return [];
492
+ }
493
+ /**
494
+ * List flow runs for this mob, optionally filtered to one `flowId`.
495
+ * Relays `MobHandle::list_runs`. Each {@link MobRun} carries the full
496
+ * meerkat ledger projection — `step_ledger`, `failure_ledger`,
497
+ * `frames`, `loops`, `loop_iteration_ledger`, `flow_state`,
498
+ * `activation_params`, etc. — verbatim from the wire JSON.
499
+ */
500
+ async listRuns(flowId) {
501
+ const params = {};
502
+ if (flowId !== undefined)
503
+ params.flow_id = flowId;
504
+ const raw = await this._runtime._rpc("mobkit/list_runs", params);
505
+ let runs = [];
506
+ if (Array.isArray(raw)) {
507
+ runs = raw;
508
+ }
509
+ else if (typeof raw === "object" && raw !== null) {
510
+ const maybe = raw.runs;
511
+ if (Array.isArray(maybe)) {
512
+ runs = maybe;
513
+ }
514
+ }
515
+ const result = [];
516
+ for (const entry of runs) {
517
+ if (typeof entry === "object" && entry !== null) {
518
+ result.push((0, types_js_1.parseMobRun)(entry));
519
+ }
520
+ }
521
+ return result;
522
+ }
523
+ /**
524
+ * Start a flow run and return its run ID. Relays meerkat 0.6's
525
+ * `MobHandle::run_flow`. `params` is forwarded verbatim as the flow's
526
+ * activation params (any JSON value).
527
+ */
528
+ async runFlow(flowId, params = null) {
529
+ const raw = await this._runtime._rpc("mobkit/run_flow", {
530
+ flow_id: flowId,
531
+ params,
532
+ });
533
+ if (typeof raw === "object" && raw !== null) {
534
+ const runId = raw.run_id;
535
+ if (typeof runId === "string") {
536
+ return runId;
537
+ }
538
+ }
539
+ throw new Error(`unexpected run_flow response: ${JSON.stringify(raw)}`);
540
+ }
325
541
  // -- Routing ------------------------------------------------------------
326
542
  async resolveRouting(recipient, options) {
327
543
  return (0, types_js_1.parseRoutingResolution)(await this._runtime._rpc("mobkit/routing/resolve", {
@@ -447,6 +663,64 @@ class MobHandle {
447
663
  async reconcileEdges() {
448
664
  return (0, types_js_1.parseReconcileEdgesReport)(await this._runtime._rpc("mobkit/reconcile_edges"));
449
665
  }
666
+ // -- Mob/run labels — mobkit-side sidecar metadata ----------------------
667
+ /**
668
+ * Replace the label set associated with this mob.
669
+ *
670
+ * Mobkit owns these labels — they are separate from meerkat-mob's
671
+ * member-level labels. Replacement is wholesale; pass `{}` to clear.
672
+ */
673
+ async setMobLabels(labels) {
674
+ await this._runtime._rpc("mobkit/mob_labels/set", { labels });
675
+ }
676
+ /** Return the label set associated with this mob (or `{}`). */
677
+ async getMobLabels() {
678
+ const raw = await this._runtime._rpc("mobkit/mob_labels/get");
679
+ if (typeof raw !== "object" || raw === null)
680
+ return {};
681
+ const labels = raw.labels;
682
+ if (typeof labels !== "object" || labels === null)
683
+ return {};
684
+ const out = {};
685
+ for (const [k, v] of Object.entries(labels)) {
686
+ out[k] = String(v);
687
+ }
688
+ return out;
689
+ }
690
+ /** Remove the label set associated with this mob. */
691
+ async deleteMobLabels() {
692
+ await this._runtime._rpc("mobkit/mob_labels/delete");
693
+ }
694
+ /**
695
+ * Replace the label set associated with `runId` under this mob.
696
+ * Replacement is wholesale (see {@link setMobLabels}).
697
+ */
698
+ async setRunLabels(runId, labels) {
699
+ await this._runtime._rpc("mobkit/run_labels/set", {
700
+ run_id: runId,
701
+ labels,
702
+ });
703
+ }
704
+ /** Return the label set for `runId` (or `{}`). */
705
+ async getRunLabels(runId) {
706
+ const raw = await this._runtime._rpc("mobkit/run_labels/get", {
707
+ run_id: runId,
708
+ });
709
+ if (typeof raw !== "object" || raw === null)
710
+ return {};
711
+ const labels = raw.labels;
712
+ if (typeof labels !== "object" || labels === null)
713
+ return {};
714
+ const out = {};
715
+ for (const [k, v] of Object.entries(labels)) {
716
+ out[k] = String(v);
717
+ }
718
+ return out;
719
+ }
720
+ /** Remove the label set for `runId`. */
721
+ async deleteRunLabels(runId) {
722
+ await this._runtime._rpc("mobkit/run_labels/delete", { run_id: runId });
723
+ }
450
724
  }
451
725
  exports.MobHandle = MobHandle;
452
726
  // -- ToolCaller -----------------------------------------------------------
@@ -499,8 +773,18 @@ class SseBridge {
499
773
  yield* this._streamSse(url);
500
774
  }
501
775
  async *_streamSse(url) {
502
- const body = await this._fetchSseStream(url);
503
- yield* (0, sse_js_1.parseSseStream)(body);
776
+ // Pre-fix, breaking out of the consumer iterator left the
777
+ // underlying http.ClientRequest open — sockets and Node refs
778
+ // accumulated. Now: tie the request lifetime to the generator via
779
+ // try/finally so consumer `break`/`throw`/`return` always destroys
780
+ // the request.
781
+ const { body, destroy } = await this._fetchSseStream(url);
782
+ try {
783
+ yield* (0, sse_js_1.parseSseStream)(body);
784
+ }
785
+ finally {
786
+ destroy();
787
+ }
504
788
  }
505
789
  _fetchSseStream(url) {
506
790
  const parsed = new URL(url);
@@ -520,7 +804,13 @@ class SseBridge {
520
804
  : new TextEncoder().encode(String(chunk));
521
805
  }
522
806
  })();
523
- resolve(stream);
807
+ resolve({
808
+ body: stream,
809
+ destroy: () => {
810
+ req.destroy();
811
+ res.destroy();
812
+ },
813
+ });
524
814
  });
525
815
  req.on("error", reject);
526
816
  req.end();
package/dist/cjs/sse.cjs CHANGED
@@ -62,17 +62,21 @@ async function* parseSseStream(body) {
62
62
  // Comment — skip
63
63
  continue;
64
64
  }
65
- else if (line.startsWith("id: ")) {
66
- currentId = line.slice(4);
65
+ else if (line.startsWith("id:")) {
66
+ // Pre-fix only matched `id: ` with the optional space, so SSE-
67
+ // spec-legal `id:42` (no space) was dropped, breaking resume
68
+ // cursors. Strip a single optional leading space, mirroring
69
+ // the existing `data:` fallback below.
70
+ const v = line.slice(3);
71
+ currentId = v.startsWith(" ") ? v.slice(1) : v;
67
72
  }
68
- else if (line.startsWith("event: ")) {
69
- currentEvent = line.slice(7);
70
- }
71
- else if (line.startsWith("data: ")) {
72
- currentData.push(line.slice(6));
73
+ else if (line.startsWith("event:")) {
74
+ const v = line.slice(6);
75
+ currentEvent = v.startsWith(" ") ? v.slice(1) : v;
73
76
  }
74
77
  else if (line.startsWith("data:")) {
75
- currentData.push(line.slice(5));
78
+ const v = line.slice(5);
79
+ currentData.push(v.startsWith(" ") ? v.slice(1) : v);
76
80
  }
77
81
  }
78
82
  }
@@ -6,7 +6,7 @@
6
6
  * newline-delimited JSON. Supports bidirectional callbacks from Rust.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.PersistentTransport = void 0;
9
+ exports.DEFAULT_HTTP_TRANSPORT_TIMEOUT_MS = exports.PersistentTransport = void 0;
10
10
  exports.buildJsonRpcRequest = buildJsonRpcRequest;
11
11
  exports.createGatewaySyncTransport = createGatewaySyncTransport;
12
12
  exports.createGatewayAsyncTransport = createGatewayAsyncTransport;
@@ -249,6 +249,12 @@ function createGatewayAsyncTransport(gatewayBin) {
249
249
  });
250
250
  });
251
251
  }
252
+ /**
253
+ * Default request timeout for {@link createJsonRpcHttpTransport}. A
254
+ * server that accepts the connection but never replies would otherwise
255
+ * leak the fetch task forever; pre-fix there was no timeout at all.
256
+ */
257
+ exports.DEFAULT_HTTP_TRANSPORT_TIMEOUT_MS = 60_000;
252
258
  /**
253
259
  * Create an async HTTP POST transport.
254
260
  */
@@ -258,25 +264,49 @@ function createJsonRpcHttpTransport(endpoint, options = {}) {
258
264
  if (!fetchImpl) {
259
265
  throw new Error("fetch implementation not available");
260
266
  }
267
+ const timeoutMs = options.timeoutMs === undefined
268
+ ? exports.DEFAULT_HTTP_TRANSPORT_TIMEOUT_MS
269
+ : options.timeoutMs;
261
270
  return async (request) => {
262
- const response = await fetchImpl(endpoint, {
263
- method: "POST",
264
- headers: {
265
- "content-type": "application/json",
266
- accept: "application/json",
267
- ...(options.headers ?? {}),
268
- },
269
- body: JSON.stringify(request),
270
- });
271
- const body = await response.text();
272
- if (!response.ok) {
273
- throw new Error(`http transport failed (status=${response.status}): ${body}`);
274
- }
271
+ const controller = timeoutMs > 0 ? new AbortController() : undefined;
272
+ const timer = controller !== undefined && timeoutMs > 0
273
+ ? setTimeout(() => controller.abort(), timeoutMs)
274
+ : undefined;
275
275
  try {
276
- return JSON.parse(body);
276
+ const response = await fetchImpl(endpoint, {
277
+ method: "POST",
278
+ headers: {
279
+ "content-type": "application/json",
280
+ accept: "application/json",
281
+ ...(options.headers ?? {}),
282
+ },
283
+ body: JSON.stringify(request),
284
+ signal: controller?.signal,
285
+ });
286
+ const body = await response.text();
287
+ if (!response.ok) {
288
+ throw new Error(`http transport failed (status=${response.status}): ${body}`);
289
+ }
290
+ try {
291
+ return JSON.parse(body);
292
+ }
293
+ catch {
294
+ throw new Error("http transport returned non-JSON response");
295
+ }
277
296
  }
278
- catch {
279
- throw new Error("http transport returned non-JSON response");
297
+ catch (err) {
298
+ if (err !== null &&
299
+ typeof err === "object" &&
300
+ "name" in err &&
301
+ err.name === "AbortError") {
302
+ throw new Error(`http transport timed out after ${timeoutMs}ms; server unresponsive`);
303
+ }
304
+ throw err;
305
+ }
306
+ finally {
307
+ if (timer !== undefined) {
308
+ clearTimeout(timer);
309
+ }
280
310
  }
281
311
  };
282
312
  }