@rkat/mobkit-sdk 0.5.1 → 0.6.2
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/agent-builder.d.ts +13 -1
- package/dist/agent-builder.d.ts.map +1 -1
- package/dist/agent-builder.js +166 -1
- package/dist/agent-builder.js.map +1 -1
- package/dist/builder.d.ts +28 -0
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +57 -0
- package/dist/builder.js.map +1 -1
- package/dist/cjs/agent-builder.cjs +165 -0
- package/dist/cjs/builder.cjs +57 -0
- package/dist/cjs/errors.cjs +72 -2
- package/dist/cjs/events.cjs +15 -5
- package/dist/cjs/index.cjs +37 -2
- package/dist/cjs/models.cjs +2 -2
- package/dist/cjs/runtime.cjs +306 -16
- package/dist/cjs/sse.cjs +12 -8
- package/dist/cjs/transport.cjs +47 -17
- package/dist/cjs/types.cjs +483 -5
- package/dist/errors.d.ts +38 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +68 -1
- package/dist/errors.js.map +1 -1
- package/dist/events.d.ts +7 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +15 -5
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +2 -2
- package/dist/models.d.ts.map +1 -1
- package/dist/models.js +2 -2
- package/dist/models.js.map +1 -1
- package/dist/runtime.d.ts +93 -3
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +308 -18
- package/dist/runtime.js.map +1 -1
- package/dist/sse.d.ts.map +1 -1
- package/dist/sse.js +12 -8
- package/dist/sse.js.map +1 -1
- package/dist/transport.d.ts +13 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +46 -16
- package/dist/transport.js.map +1 -1
- package/dist/types.d.ts +265 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +454 -5
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/runtime.cjs
CHANGED
|
@@ -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
|
-
|
|
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].
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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(
|
|
264
|
-
return
|
|
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,
|
|
404
|
+
async ensureMember(memberId, role, options) {
|
|
278
405
|
const params = {
|
|
279
|
-
|
|
280
|
-
|
|
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
|
-
|
|
503
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
+
const v = line.slice(5);
|
|
79
|
+
currentData.push(v.startsWith(" ") ? v.slice(1) : v);
|
|
76
80
|
}
|
|
77
81
|
}
|
|
78
82
|
}
|
package/dist/cjs/transport.cjs
CHANGED
|
@@ -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
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|