@agentcomms/events-daemon 0.16.0 → 0.18.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.
@@ -1,10 +1,25 @@
1
- import { i as serializeMessage, n as process, r as ReadBuffer } from "./mcp-DXXb3Vv3-B0sHZfig.mjs";
2
- //#region ../../node_modules/.pnpm/@modelcontextprotocol+server@2.0.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
1
+ import { i as serializeMessage, n as process, r as ReadBuffer } from "./mcp-DIH4cS6P-YuKZfqTg.mjs";
2
+ //#region ../../node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
3
+ /**
4
+ * Marks a stdout `'error'` listener that a closed transport left attached purely to
5
+ * swallow late write failures (see {@link StdioServerTransport.close}). A fresh
6
+ * transport taking over the same stream removes listeners carrying this tag in
7
+ * `start()`, so repeated create→close cycles on the process-global `process.stdout`
8
+ * don't accumulate listeners.
9
+ */
10
+ const swallowsErrorsAfterClose = Symbol("swallowsErrorsAfterClose");
3
11
  /**
4
12
  * Server transport for stdio: this communicates with an MCP client by reading from the current process' `stdin` and writing to `stdout`.
5
13
  *
6
14
  * This transport is only available in Node.js environments.
7
15
  *
16
+ * When the client closes its end of the pipe (stdin reaches end-of-file), the transport
17
+ * closes itself and fires `onclose`, per the MCP stdio binding's guidance that servers
18
+ * should exit promptly when their standard input is closed. A server that holds no other
19
+ * keep-alive handles will then exit naturally. Requests still in flight when stdin ends are
20
+ * aborted and not answered; a client that expects responses keeps stdin open until it has
21
+ * read them.
22
+ *
8
23
  * @example
9
24
  * ```ts source="./stdio.examples.ts#StdioServerTransport_basicUsage"
10
25
  * const server = new McpServer({ name: 'my-server', version: '1.0.0' });
@@ -37,17 +52,25 @@ var StdioServerTransport = class {
37
52
  this.onerror?.(error);
38
53
  };
39
54
  _onstdouterror = (error) => {
55
+ if (this._closed) return;
40
56
  this.onerror?.(error);
41
57
  this.close().catch(() => {});
42
58
  };
59
+ _onstdinclose = () => {
60
+ this.close().catch(() => {});
61
+ };
43
62
  /**
44
63
  * Starts listening for messages on `stdin`.
45
64
  */
46
65
  async start() {
47
66
  if (this._started) throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
48
67
  this._started = true;
68
+ for (const listener of this._stdout.listeners("error")) if (listener[swallowsErrorsAfterClose]) this._stdout.off("error", listener);
69
+ if (this._stdin.readableEnded || this._stdin.destroyed) setImmediate(this._onstdinclose);
49
70
  this._stdin.on("data", this._ondata);
50
71
  this._stdin.on("error", this._onerror);
72
+ this._stdin.on("end", this._onstdinclose);
73
+ this._stdin.on("close", this._onstdinclose);
51
74
  this._stdout.on("error", this._onstdouterror);
52
75
  }
53
76
  processReadBuffer() {
@@ -64,7 +87,9 @@ var StdioServerTransport = class {
64
87
  this._closed = true;
65
88
  this._stdin.off("data", this._ondata);
66
89
  this._stdin.off("error", this._onerror);
67
- this._stdout.off("error", this._onstdouterror);
90
+ this._stdin.off("end", this._onstdinclose);
91
+ this._stdin.off("close", this._onstdinclose);
92
+ this._onstdouterror[swallowsErrorsAfterClose] = true;
68
93
  if (this._stdin.listenerCount("data") === 0) this._stdin.pause();
69
94
  this._readBuffer.clear();
70
95
  this.onclose?.();
@@ -1,25 +1,4 @@
1
1
  import { canonicalJson, sha256Hex } from "@agentcomms/core";
2
- //#region src/domain/lifecycle.ts
3
- /** A content-free domain refusal. No caller should substitute an arbitrary Error message at a control boundary. */
4
- var EventDomainError = class extends Error {
5
- code;
6
- constructor(code, message) {
7
- super(message);
8
- this.name = "EventDomainError";
9
- this.code = code;
10
- }
11
- };
12
- const JUDGE_KINDS = [
13
- "typesafe",
14
- "laya",
15
- "local-endpoint"
16
- ];
17
- function isJudgeKind(value) {
18
- return typeof value === "string" && JUDGE_KINDS.includes(value);
19
- }
20
- function assertJudgeKindEnabled(kind, enabled) {
21
- if (!enabled) throw new EventDomainError("JUDGE_KIND_DISABLED", `the ${kind} judge kind is disabled`);
22
- }
23
2
  //#endregion
24
3
  //#region src/network/iana-special-purpose.ts
25
4
  /** Checked-in IANA policy; network code must never refresh or consult it at runtime. */
@@ -464,23 +443,30 @@ function embeddedAddresses(address, options) {
464
443
  embedded.push(ipv4From(address.value >> 64n));
465
444
  embedded.push(ipv4From((address.value ^ IPV4_MAX) & IPV4_MAX));
466
445
  }
446
+ const isatapInterface = address.value >> 32n & IPV4_MAX;
447
+ if (isatapInterface === 24318n || isatapInterface === 33578750n) embedded.push(ipv4From(address.value));
467
448
  return embedded;
468
449
  }
469
450
  function assertOne(address, approved, options, seen) {
470
451
  if (seen.has(`${address.family}:${address.value}`)) return [];
471
452
  seen.add(`${address.family}:${address.value}`);
472
453
  if (isUnconditionallyDenied(address)) throw new AddressPolicyError(`address ${address.address} is metadata or link-local and is always refused`);
473
- const explicitlyApproved = approved.some((entry) => inCidr(address, entry));
474
- if (!globallyReachable(address) && !explicitlyApproved) throw new AddressPolicyError(`non-global address ${address.address} needs an exact approvedAddressSet entry`);
475
- if (!explicitlyApproved) throw new AddressPolicyError(`address ${address.address} is not in the approvedAddressSet`);
454
+ if (options.addressMode === "global-only") {
455
+ if (!globallyReachable(address)) throw new AddressPolicyError(`non-global address ${address.address} is refused by global-only policy`);
456
+ } else {
457
+ if (approved === void 0) throw new AddressPolicyError("approvedAddressSet was unavailable");
458
+ const explicitlyApproved = approved.some((entry) => inCidr(address, entry));
459
+ if (!globallyReachable(address) && !explicitlyApproved) throw new AddressPolicyError(`non-global address ${address.address} needs an exact approvedAddressSet entry`);
460
+ if (!explicitlyApproved) throw new AddressPolicyError(`address ${address.address} is not in the approvedAddressSet`);
461
+ }
476
462
  const nested = embeddedAddresses(address, options);
477
463
  for (const child of nested) assertOne(child, approved, options, seen);
478
464
  return nested;
479
465
  }
480
- /** Validates the literal itself and every embedded transition address against the exact approved set. */
466
+ /** Validates the literal itself and every embedded transition address under the selected exact-set or global-only policy. */
481
467
  function assertAddressAllowed(input, options) {
482
468
  const address = parseIpLiteral(input);
483
- const embedded = assertOne(address, parseApprovedAddressSet(options.approvedAddressSet), options, /* @__PURE__ */ new Set());
469
+ const embedded = assertOne(address, options.addressMode === "global-only" ? void 0 : parseApprovedAddressSet(options.approvedAddressSet), options, /* @__PURE__ */ new Set());
484
470
  return {
485
471
  address: address.address,
486
472
  family: address.family,
@@ -518,6 +504,31 @@ function validateLocalEndpoint(input, approvedAddressSet) {
518
504
  };
519
505
  }
520
506
  //#endregion
507
+ //#region src/domain/lifecycle.ts
508
+ /** A content-free domain refusal. No caller should substitute an arbitrary Error message at a control boundary. */
509
+ var EventDomainError = class extends Error {
510
+ code;
511
+ constructor(code, message) {
512
+ super(message);
513
+ this.name = "EventDomainError";
514
+ this.code = code;
515
+ }
516
+ };
517
+ const JUDGE_KIND_TYPESAFE = "typesafe";
518
+ const JUDGE_KIND_LAYA = "laya";
519
+ const JUDGE_KIND_LOCAL_ENDPOINT = "local-endpoint";
520
+ const JUDGE_KINDS = [
521
+ JUDGE_KIND_TYPESAFE,
522
+ JUDGE_KIND_LAYA,
523
+ JUDGE_KIND_LOCAL_ENDPOINT
524
+ ];
525
+ function isJudgeKind(value) {
526
+ return typeof value === "string" && JUDGE_KINDS.includes(value);
527
+ }
528
+ function assertJudgeKindEnabled(kind, enabled) {
529
+ if (!enabled) throw new EventDomainError("JUDGE_KIND_DISABLED", `the ${kind} judge kind is disabled`);
530
+ }
531
+ //#endregion
521
532
  //#region src/domain/webhook-target.ts
522
533
  function fail(message) {
523
534
  throw new EventDomainError("VERSION_DOCUMENT_INVALID", message);
@@ -659,4 +670,4 @@ function webhookDeliveryTarget(document) {
659
670
  };
660
671
  }
661
672
  //#endregion
662
- export { AddressPolicyError as a, parseIpLiteral as c, isJudgeKind as d, webhookDeliveryTarget as i, EventDomainError as l, canonicalWebhookTarget as n, assertAddressAllowed as o, secretWebhookUrlDescriptor as r, assertApprovedAddressSet as s, canonicalSecretWebhookUrl as t, assertJudgeKindEnabled as u };
673
+ export { EventDomainError as a, JUDGE_KIND_LOCAL_ENDPOINT as c, isJudgeKind as d, validateLocalEndpoint as f, parseIpLiteral as g, assertApprovedAddressSet as h, webhookDeliveryTarget as i, JUDGE_KIND_TYPESAFE as l, assertAddressAllowed as m, canonicalWebhookTarget as n, JUDGE_KINDS as o, AddressPolicyError as p, secretWebhookUrlDescriptor as r, JUDGE_KIND_LAYA as s, canonicalSecretWebhookUrl as t, assertJudgeKindEnabled as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentcomms/events-daemon",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "The local event service for agent-communications: rules you approve deliver Gmail, Slack, Resend and WhatsApp events to a signed webhook, a local live stream or a dry-run log.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,19 +34,19 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@agentcomms/gmail": "0.16.0",
38
- "@agentcomms/events": "0.16.0",
39
- "@agentcomms/slack": "0.16.0",
40
- "@agentcomms/whatsapp": "0.16.0",
41
- "@agentcomms/core": "0.16.0",
42
- "@agentcomms/resend": "0.16.0"
37
+ "@agentcomms/events": "0.18.0",
38
+ "@agentcomms/resend": "0.18.0",
39
+ "@agentcomms/gmail": "0.18.0",
40
+ "@agentcomms/slack": "0.18.0",
41
+ "@agentcomms/core": "0.18.0",
42
+ "@agentcomms/whatsapp": "0.18.0"
43
43
  },
44
44
  "devDependencies": {
45
- "@modelcontextprotocol/client": "2.0.0",
46
- "@modelcontextprotocol/server": "^2.0.0",
45
+ "@modelcontextprotocol/client": "2.3.1",
46
+ "@modelcontextprotocol/server": "^2.3.1",
47
47
  "ajv": "8.20.0",
48
48
  "commander": "^15.0.0",
49
- "playwright": "1.61.1",
49
+ "playwright": "1.64.0",
50
50
  "tsdown": "0.23.0",
51
51
  "typescript": "7.0.2",
52
52
  "zod": "^4.6.5"
@@ -70,5 +70,5 @@
70
70
  "typecheck": "tsc -p tsconfig.json",
71
71
  "test": "node --import ../../test/helpers/loopback-seal-preload.mjs --experimental-strip-types --disable-warning=ExperimentalWarning --test \"test/**/*.test.ts\""
72
72
  },
73
- "gitHead": "01cee751d91be360cc363338cfe432672745f431"
73
+ "gitHead": "a55c5383b35a8214b9e481e2a148b0e29a663a9f"
74
74
  }
@@ -1,2 +0,0 @@
1
- import { n as RECORD_LAYOUTS } from "./records-3rGS8spn.mjs";
2
- export { RECORD_LAYOUTS };