@ethisyscore/extension-runtime 1.34.0 → 1.36.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
@@ -76,6 +76,13 @@ var WorkerRemoteDomTransport = class {
76
76
  coalesceMs;
77
77
  maxConcurrentMcpRequests;
78
78
  abortController;
79
+ // Per-request AbortControllers keyed by request id. An inbound
80
+ // `ethisys:mcp:abort` envelope (the worker posts one when a hook's
81
+ // AbortSignal fires on unmount / arg change) aborts just that request;
82
+ // dispose() fans out to every registered controller. Without this a
83
+ // cancelled call — most costly for uploadDocument — keeps streaming to the
84
+ // kernel even though the plugin promise already rejected.
85
+ inFlightAborts = /* @__PURE__ */ new Map();
79
86
  inFlightMcpRequests = 0;
80
87
  remoteDomConsumer;
81
88
  bridgeMessageConsumer;
@@ -263,6 +270,10 @@ var WorkerRemoteDomTransport = class {
263
270
  this.disposed = true;
264
271
  try {
265
272
  this.abortController.abort();
273
+ for (const controller of this.inFlightAborts.values()) {
274
+ controller.abort();
275
+ }
276
+ this.inFlightAborts.clear();
266
277
  } catch {
267
278
  }
268
279
  try {
@@ -301,6 +312,12 @@ var WorkerRemoteDomTransport = class {
301
312
  case "ethisys:mcp:getResource":
302
313
  this.dispatchMcp(message, "ethisys:mcp:getResource:result", (m) => this.handleGetResource(m));
303
314
  return;
315
+ case "ethisys:mcp:uploadDocument":
316
+ this.dispatchMcp(message, "ethisys:mcp:uploadDocument:result", (m) => this.handleUploadDocument(m));
317
+ return;
318
+ case "ethisys:mcp:abort":
319
+ this.inFlightAborts.get(message.id ?? "")?.abort();
320
+ return;
304
321
  case "ethisys:remotedom":
305
322
  this.remoteDomConsumer?.(message.payload);
306
323
  return;
@@ -330,10 +347,37 @@ var WorkerRemoteDomTransport = class {
330
347
  return;
331
348
  }
332
349
  this.inFlightMcpRequests++;
350
+ this.registerRequestAbort(message.id);
333
351
  handler(message).finally(() => {
352
+ this.releaseRequestAbort(message.id);
334
353
  this.inFlightMcpRequests = Math.max(0, this.inFlightMcpRequests - 1);
335
354
  });
336
355
  }
356
+ /**
357
+ * Create a per-request AbortController and register it under the request id
358
+ * so an inbound `ethisys:mcp:abort` can cancel just this call. If the
359
+ * transport is already disposed the controller starts aborted so the
360
+ * handler's `mcpClient.fetch` short-circuits immediately.
361
+ */
362
+ registerRequestAbort(id) {
363
+ const controller = new AbortController();
364
+ if (this.abortController.signal.aborted) {
365
+ controller.abort();
366
+ }
367
+ this.inFlightAborts.set(id, controller);
368
+ }
369
+ /** Drop a settled request's AbortController. */
370
+ releaseRequestAbort(id) {
371
+ this.inFlightAborts.delete(id);
372
+ }
373
+ /**
374
+ * The signal to hand to `mcpClient.fetch` for a given request: the
375
+ * per-request controller when registered (client cancel path), falling back
376
+ * to the dispose-level controller.
377
+ */
378
+ requestSignal(id) {
379
+ return this.inFlightAborts.get(id)?.signal ?? this.abortController.signal;
380
+ }
337
381
  async handleInvokeTool(message) {
338
382
  let token;
339
383
  try {
@@ -351,7 +395,7 @@ var WorkerRemoteDomTransport = class {
351
395
  name: message.name,
352
396
  args: message.args,
353
397
  capabilityToken: token,
354
- signal: this.abortController.signal
398
+ signal: this.requestSignal(message.id)
355
399
  });
356
400
  this.safePostMessage({
357
401
  id: message.id,
@@ -380,7 +424,7 @@ var WorkerRemoteDomTransport = class {
380
424
  kind: "getResource",
381
425
  uri: message.uri,
382
426
  capabilityToken: token,
383
- signal: this.abortController.signal
427
+ signal: this.requestSignal(message.id)
384
428
  });
385
429
  this.safePostMessage({
386
430
  id: message.id,
@@ -393,6 +437,36 @@ var WorkerRemoteDomTransport = class {
393
437
  this.replyError(message.id, "ethisys:mcp:getResource:result", err);
394
438
  }
395
439
  }
440
+ async handleUploadDocument(message) {
441
+ let token;
442
+ try {
443
+ token = await this.capabilityTokenProvider();
444
+ } catch (err) {
445
+ this.replyError(message.id, "ethisys:mcp:uploadDocument:result", err);
446
+ return;
447
+ }
448
+ if (this.disposed) {
449
+ return;
450
+ }
451
+ try {
452
+ const result = await this.mcpClient.fetch({
453
+ kind: "uploadDocument",
454
+ meta: message.meta,
455
+ buffer: message.buffer,
456
+ capabilityToken: token,
457
+ signal: this.requestSignal(message.id)
458
+ });
459
+ this.safePostMessage({
460
+ id: message.id,
461
+ type: "ethisys:mcp:uploadDocument:result",
462
+ ok: result.ok,
463
+ data: result.data,
464
+ error: result.error
465
+ });
466
+ } catch (err) {
467
+ this.replyError(message.id, "ethisys:mcp:uploadDocument:result", err);
468
+ }
469
+ }
396
470
  replyError(id, type, err) {
397
471
  const message = err instanceof Error ? err.message : "MCP request failed";
398
472
  this.safePostMessage({ id, type, ok: false, error: message });
@@ -713,6 +787,17 @@ window.__MOCK_HOST_REGISTRY__ = registry;
713
787
  }
714
788
  var defaultMockMcpClient = {
715
789
  fetch: async (req) => {
790
+ if (req.kind === "uploadDocument") {
791
+ return {
792
+ ok: true,
793
+ data: {
794
+ storedDocumentId: `mock-${req.meta.entityName}-${req.meta.fileName}`,
795
+ fileName: req.meta.fileName,
796
+ contentType: req.meta.contentType,
797
+ sizeBytes: req.buffer.byteLength
798
+ }
799
+ };
800
+ }
716
801
  const echo = req.kind === "invokeTool" ? { tool: req.name, args: req.args } : { resource: req.uri };
717
802
  return { ok: true, data: { mockHost: true, ...echo } };
718
803
  }