@ethisyscore/extension-runtime 1.34.0 → 1.35.0

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 (33) hide show
  1. package/dist/{bridge-client-UK3qcGoi.d.ts → bridge-client-DD99netz.d.ts} +2 -33
  2. package/dist/{bridge-client-CIThO7jZ.d.cts → bridge-client-DzRcKIJT.d.cts} +2 -33
  3. package/dist/bridge-envelopes-DA6vxbyb.d.cts +151 -0
  4. package/dist/bridge-envelopes-DA6vxbyb.d.ts +151 -0
  5. package/dist/host/index.cjs +76 -2
  6. package/dist/host/index.cjs.map +1 -1
  7. package/dist/host/index.d.cts +3 -3
  8. package/dist/host/index.d.ts +3 -3
  9. package/dist/host/index.js +76 -2
  10. package/dist/host/index.js.map +1 -1
  11. package/dist/mock-host/cli.cjs +87 -2
  12. package/dist/mock-host/cli.cjs.map +1 -1
  13. package/dist/mock-host/cli.d.cts +2 -2
  14. package/dist/mock-host/cli.d.ts +2 -2
  15. package/dist/mock-host/cli.js +87 -2
  16. package/dist/mock-host/cli.js.map +1 -1
  17. package/dist/mock-host/index.cjs +41 -1
  18. package/dist/mock-host/index.cjs.map +1 -1
  19. package/dist/mock-host/index.d.cts +19 -7
  20. package/dist/mock-host/index.d.ts +19 -7
  21. package/dist/mock-host/index.js +41 -1
  22. package/dist/mock-host/index.js.map +1 -1
  23. package/dist/plugin/index.cjs +15 -3
  24. package/dist/plugin/index.cjs.map +1 -1
  25. package/dist/plugin/index.d.cts +13 -5
  26. package/dist/plugin/index.d.ts +13 -5
  27. package/dist/plugin/index.js +15 -4
  28. package/dist/plugin/index.js.map +1 -1
  29. package/dist/{transport-BN9Mzn_m.d.cts → transport-CHa8ESUx.d.ts} +39 -4
  30. package/dist/{transport-Jfd9KXAh.d.ts → transport-DJE6ljme.d.cts} +39 -4
  31. package/package.json +1 -1
  32. package/dist/bridge-envelopes-BRKGSiSC.d.cts +0 -63
  33. package/dist/bridge-envelopes-BRKGSiSC.d.ts +0 -63
@@ -54,6 +54,13 @@ var WorkerRemoteDomTransport = class {
54
54
  coalesceMs;
55
55
  maxConcurrentMcpRequests;
56
56
  abortController;
57
+ // Per-request AbortControllers keyed by request id. An inbound
58
+ // `ethisys:mcp:abort` envelope (the worker posts one when a hook's
59
+ // AbortSignal fires on unmount / arg change) aborts just that request;
60
+ // dispose() fans out to every registered controller. Without this a
61
+ // cancelled call — most costly for uploadDocument — keeps streaming to the
62
+ // kernel even though the plugin promise already rejected.
63
+ inFlightAborts = /* @__PURE__ */ new Map();
57
64
  inFlightMcpRequests = 0;
58
65
  remoteDomConsumer;
59
66
  bridgeMessageConsumer;
@@ -241,6 +248,10 @@ var WorkerRemoteDomTransport = class {
241
248
  this.disposed = true;
242
249
  try {
243
250
  this.abortController.abort();
251
+ for (const controller of this.inFlightAborts.values()) {
252
+ controller.abort();
253
+ }
254
+ this.inFlightAborts.clear();
244
255
  } catch {
245
256
  }
246
257
  try {
@@ -279,6 +290,12 @@ var WorkerRemoteDomTransport = class {
279
290
  case "ethisys:mcp:getResource":
280
291
  this.dispatchMcp(message, "ethisys:mcp:getResource:result", (m) => this.handleGetResource(m));
281
292
  return;
293
+ case "ethisys:mcp:uploadDocument":
294
+ this.dispatchMcp(message, "ethisys:mcp:uploadDocument:result", (m) => this.handleUploadDocument(m));
295
+ return;
296
+ case "ethisys:mcp:abort":
297
+ this.inFlightAborts.get(message.id ?? "")?.abort();
298
+ return;
282
299
  case "ethisys:remotedom":
283
300
  this.remoteDomConsumer?.(message.payload);
284
301
  return;
@@ -308,10 +325,37 @@ var WorkerRemoteDomTransport = class {
308
325
  return;
309
326
  }
310
327
  this.inFlightMcpRequests++;
328
+ this.registerRequestAbort(message.id);
311
329
  handler(message).finally(() => {
330
+ this.releaseRequestAbort(message.id);
312
331
  this.inFlightMcpRequests = Math.max(0, this.inFlightMcpRequests - 1);
313
332
  });
314
333
  }
334
+ /**
335
+ * Create a per-request AbortController and register it under the request id
336
+ * so an inbound `ethisys:mcp:abort` can cancel just this call. If the
337
+ * transport is already disposed the controller starts aborted so the
338
+ * handler's `mcpClient.fetch` short-circuits immediately.
339
+ */
340
+ registerRequestAbort(id) {
341
+ const controller = new AbortController();
342
+ if (this.abortController.signal.aborted) {
343
+ controller.abort();
344
+ }
345
+ this.inFlightAborts.set(id, controller);
346
+ }
347
+ /** Drop a settled request's AbortController. */
348
+ releaseRequestAbort(id) {
349
+ this.inFlightAborts.delete(id);
350
+ }
351
+ /**
352
+ * The signal to hand to `mcpClient.fetch` for a given request: the
353
+ * per-request controller when registered (client cancel path), falling back
354
+ * to the dispose-level controller.
355
+ */
356
+ requestSignal(id) {
357
+ return this.inFlightAborts.get(id)?.signal ?? this.abortController.signal;
358
+ }
315
359
  async handleInvokeTool(message) {
316
360
  let token;
317
361
  try {
@@ -329,7 +373,7 @@ var WorkerRemoteDomTransport = class {
329
373
  name: message.name,
330
374
  args: message.args,
331
375
  capabilityToken: token,
332
- signal: this.abortController.signal
376
+ signal: this.requestSignal(message.id)
333
377
  });
334
378
  this.safePostMessage({
335
379
  id: message.id,
@@ -358,7 +402,7 @@ var WorkerRemoteDomTransport = class {
358
402
  kind: "getResource",
359
403
  uri: message.uri,
360
404
  capabilityToken: token,
361
- signal: this.abortController.signal
405
+ signal: this.requestSignal(message.id)
362
406
  });
363
407
  this.safePostMessage({
364
408
  id: message.id,
@@ -371,6 +415,36 @@ var WorkerRemoteDomTransport = class {
371
415
  this.replyError(message.id, "ethisys:mcp:getResource:result", err);
372
416
  }
373
417
  }
418
+ async handleUploadDocument(message) {
419
+ let token;
420
+ try {
421
+ token = await this.capabilityTokenProvider();
422
+ } catch (err) {
423
+ this.replyError(message.id, "ethisys:mcp:uploadDocument:result", err);
424
+ return;
425
+ }
426
+ if (this.disposed) {
427
+ return;
428
+ }
429
+ try {
430
+ const result = await this.mcpClient.fetch({
431
+ kind: "uploadDocument",
432
+ meta: message.meta,
433
+ buffer: message.buffer,
434
+ capabilityToken: token,
435
+ signal: this.requestSignal(message.id)
436
+ });
437
+ this.safePostMessage({
438
+ id: message.id,
439
+ type: "ethisys:mcp:uploadDocument:result",
440
+ ok: result.ok,
441
+ data: result.data,
442
+ error: result.error
443
+ });
444
+ } catch (err) {
445
+ this.replyError(message.id, "ethisys:mcp:uploadDocument:result", err);
446
+ }
447
+ }
374
448
  replyError(id, type, err) {
375
449
  const message = err instanceof Error ? err.message : "MCP request failed";
376
450
  this.safePostMessage({ id, type, ok: false, error: message });
@@ -691,6 +765,17 @@ window.__MOCK_HOST_REGISTRY__ = registry;
691
765
  }
692
766
  var defaultMockMcpClient = {
693
767
  fetch: async (req) => {
768
+ if (req.kind === "uploadDocument") {
769
+ return {
770
+ ok: true,
771
+ data: {
772
+ storedDocumentId: `mock-${req.meta.entityName}-${req.meta.fileName}`,
773
+ fileName: req.meta.fileName,
774
+ contentType: req.meta.contentType,
775
+ sizeBytes: req.buffer.byteLength
776
+ }
777
+ };
778
+ }
694
779
  const echo = req.kind === "invokeTool" ? { tool: req.name, args: req.args } : { resource: req.uri };
695
780
  return { ok: true, data: { mockHost: true, ...echo } };
696
781
  }