@animalabs/agent-framework 0.5.6 → 0.6.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 (177) hide show
  1. package/dist/src/agent.d.ts +20 -4
  2. package/dist/src/agent.d.ts.map +1 -1
  3. package/dist/src/agent.js +45 -14
  4. package/dist/src/agent.js.map +1 -1
  5. package/dist/src/framework.d.ts +220 -5
  6. package/dist/src/framework.d.ts.map +1 -1
  7. package/dist/src/framework.js +1489 -69
  8. package/dist/src/framework.js.map +1 -1
  9. package/dist/src/gate/event-gate.d.ts +71 -1
  10. package/dist/src/gate/event-gate.d.ts.map +1 -1
  11. package/dist/src/gate/event-gate.js +292 -9
  12. package/dist/src/gate/event-gate.js.map +1 -1
  13. package/dist/src/gate/gate-script-worker.d.ts +2 -0
  14. package/dist/src/gate/gate-script-worker.d.ts.map +1 -0
  15. package/dist/src/gate/gate-script-worker.js +69 -0
  16. package/dist/src/gate/gate-script-worker.js.map +1 -0
  17. package/dist/src/gate/gate-script.d.ts +44 -0
  18. package/dist/src/gate/gate-script.d.ts.map +1 -0
  19. package/dist/src/gate/gate-script.js +164 -0
  20. package/dist/src/gate/gate-script.js.map +1 -0
  21. package/dist/src/gate/types.d.ts +35 -3
  22. package/dist/src/gate/types.d.ts.map +1 -1
  23. package/dist/src/index.d.ts +2 -0
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +2 -0
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/mcpl/channel-registry.d.ts +93 -1
  28. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  29. package/dist/src/mcpl/channel-registry.js +260 -6
  30. package/dist/src/mcpl/channel-registry.js.map +1 -1
  31. package/dist/src/mcpl/checkpoint-manager.d.ts +7 -0
  32. package/dist/src/mcpl/checkpoint-manager.d.ts.map +1 -1
  33. package/dist/src/mcpl/checkpoint-manager.js +15 -0
  34. package/dist/src/mcpl/checkpoint-manager.js.map +1 -1
  35. package/dist/src/mcpl/conversation-router.d.ts +161 -0
  36. package/dist/src/mcpl/conversation-router.d.ts.map +1 -0
  37. package/dist/src/mcpl/conversation-router.js +179 -0
  38. package/dist/src/mcpl/conversation-router.js.map +1 -0
  39. package/dist/src/mcpl/feature-set-manager.d.ts.map +1 -1
  40. package/dist/src/mcpl/feature-set-manager.js +10 -1
  41. package/dist/src/mcpl/feature-set-manager.js.map +1 -1
  42. package/dist/src/mcpl/index.d.ts +2 -0
  43. package/dist/src/mcpl/index.d.ts.map +1 -1
  44. package/dist/src/mcpl/index.js +2 -0
  45. package/dist/src/mcpl/index.js.map +1 -1
  46. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  47. package/dist/src/mcpl/push-handler.js +1 -0
  48. package/dist/src/mcpl/push-handler.js.map +1 -1
  49. package/dist/src/mcpl/server-connection.d.ts +35 -30
  50. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  51. package/dist/src/mcpl/server-connection.js +149 -206
  52. package/dist/src/mcpl/server-connection.js.map +1 -1
  53. package/dist/src/mcpl/transport.d.ts +98 -0
  54. package/dist/src/mcpl/transport.d.ts.map +1 -0
  55. package/dist/src/mcpl/transport.js +281 -0
  56. package/dist/src/mcpl/transport.js.map +1 -0
  57. package/dist/src/mcpl/types.d.ts +42 -2
  58. package/dist/src/mcpl/types.d.ts.map +1 -1
  59. package/dist/src/mcpl/types.js.map +1 -1
  60. package/dist/src/module-registry.d.ts +5 -1
  61. package/dist/src/module-registry.d.ts.map +1 -1
  62. package/dist/src/module-registry.js +16 -2
  63. package/dist/src/module-registry.js.map +1 -1
  64. package/dist/src/modules/discord/index.d.ts +10 -0
  65. package/dist/src/modules/discord/index.d.ts.map +1 -1
  66. package/dist/src/modules/discord/index.js +83 -0
  67. package/dist/src/modules/discord/index.js.map +1 -1
  68. package/dist/src/prose-segments.d.ts +18 -0
  69. package/dist/src/prose-segments.d.ts.map +1 -0
  70. package/dist/src/prose-segments.js +39 -0
  71. package/dist/src/prose-segments.js.map +1 -0
  72. package/dist/src/runtime/liveness-watchdog-worker.d.ts +2 -0
  73. package/dist/src/runtime/liveness-watchdog-worker.d.ts.map +1 -0
  74. package/dist/src/runtime/liveness-watchdog-worker.js +57 -0
  75. package/dist/src/runtime/liveness-watchdog-worker.js.map +1 -0
  76. package/dist/src/runtime/liveness-watchdog.d.ts +36 -0
  77. package/dist/src/runtime/liveness-watchdog.d.ts.map +1 -0
  78. package/dist/src/runtime/liveness-watchdog.js +106 -0
  79. package/dist/src/runtime/liveness-watchdog.js.map +1 -0
  80. package/dist/src/tool-result-history.d.ts +17 -0
  81. package/dist/src/tool-result-history.d.ts.map +1 -0
  82. package/dist/src/tool-result-history.js +60 -0
  83. package/dist/src/tool-result-history.js.map +1 -0
  84. package/dist/src/types/agent.d.ts +21 -0
  85. package/dist/src/types/agent.d.ts.map +1 -1
  86. package/dist/src/types/framework.d.ts +22 -0
  87. package/dist/src/types/framework.d.ts.map +1 -1
  88. package/dist/src/types/module.d.ts +27 -0
  89. package/dist/src/types/module.d.ts.map +1 -1
  90. package/dist/src/types/trace.d.ts +28 -0
  91. package/dist/src/types/trace.d.ts.map +1 -1
  92. package/dist/test/channel-registry-routing.test.d.ts +2 -0
  93. package/dist/test/channel-registry-routing.test.d.ts.map +1 -0
  94. package/dist/test/channel-registry-routing.test.js +182 -0
  95. package/dist/test/channel-registry-routing.test.js.map +1 -0
  96. package/dist/test/checkpoint-attribution.test.d.ts +2 -0
  97. package/dist/test/checkpoint-attribution.test.d.ts.map +1 -0
  98. package/dist/test/checkpoint-attribution.test.js +40 -0
  99. package/dist/test/checkpoint-attribution.test.js.map +1 -0
  100. package/dist/test/conversation-router.test.d.ts +2 -0
  101. package/dist/test/conversation-router.test.d.ts.map +1 -0
  102. package/dist/test/conversation-router.test.js +160 -0
  103. package/dist/test/conversation-router.test.js.map +1 -0
  104. package/dist/test/conversation-routing.test.d.ts +7 -0
  105. package/dist/test/conversation-routing.test.d.ts.map +1 -0
  106. package/dist/test/conversation-routing.test.js +203 -0
  107. package/dist/test/conversation-routing.test.js.map +1 -0
  108. package/dist/test/event-gate-policy-mutation.test.d.ts +2 -0
  109. package/dist/test/event-gate-policy-mutation.test.d.ts.map +1 -0
  110. package/dist/test/event-gate-policy-mutation.test.js +137 -0
  111. package/dist/test/event-gate-policy-mutation.test.js.map +1 -0
  112. package/dist/test/event-gate-script.test.d.ts +2 -0
  113. package/dist/test/event-gate-script.test.d.ts.map +1 -0
  114. package/dist/test/event-gate-script.test.js +95 -0
  115. package/dist/test/event-gate-script.test.js.map +1 -0
  116. package/dist/test/event-gate-tags.test.d.ts +2 -0
  117. package/dist/test/event-gate-tags.test.d.ts.map +1 -0
  118. package/dist/test/event-gate-tags.test.js +76 -0
  119. package/dist/test/event-gate-tags.test.js.map +1 -0
  120. package/dist/test/framework.test.js +73 -1
  121. package/dist/test/framework.test.js.map +1 -1
  122. package/dist/test/helpers/mock-membrane.d.ts +41 -0
  123. package/dist/test/helpers/mock-membrane.d.ts.map +1 -0
  124. package/dist/test/helpers/mock-membrane.js +161 -0
  125. package/dist/test/helpers/mock-membrane.js.map +1 -0
  126. package/dist/test/inference-failure-observability.test.d.ts +2 -0
  127. package/dist/test/inference-failure-observability.test.d.ts.map +1 -0
  128. package/dist/test/inference-failure-observability.test.js +75 -0
  129. package/dist/test/inference-failure-observability.test.js.map +1 -0
  130. package/dist/test/liveness-watchdog.test.d.ts +2 -0
  131. package/dist/test/liveness-watchdog.test.d.ts.map +1 -0
  132. package/dist/test/liveness-watchdog.test.js +78 -0
  133. package/dist/test/liveness-watchdog.test.js.map +1 -0
  134. package/dist/test/mcpl-ws-transport.test.d.ts +2 -0
  135. package/dist/test/mcpl-ws-transport.test.d.ts.map +1 -0
  136. package/dist/test/mcpl-ws-transport.test.js +155 -0
  137. package/dist/test/mcpl-ws-transport.test.js.map +1 -0
  138. package/dist/test/prose-segments.test.d.ts +2 -0
  139. package/dist/test/prose-segments.test.d.ts.map +1 -0
  140. package/dist/test/prose-segments.test.js +52 -0
  141. package/dist/test/prose-segments.test.js.map +1 -0
  142. package/dist/test/tool-result-history.test.d.ts +7 -0
  143. package/dist/test/tool-result-history.test.d.ts.map +1 -0
  144. package/dist/test/tool-result-history.test.js +77 -0
  145. package/dist/test/tool-result-history.test.js.map +1 -0
  146. package/dist/test/trunk-channel-routing.test.d.ts +19 -0
  147. package/dist/test/trunk-channel-routing.test.d.ts.map +1 -0
  148. package/dist/test/trunk-channel-routing.test.js +175 -0
  149. package/dist/test/trunk-channel-routing.test.js.map +1 -0
  150. package/dist/tsconfig.tsbuildinfo +1 -1
  151. package/package.json +3 -3
  152. package/src/agent.ts +53 -18
  153. package/src/framework.ts +1685 -71
  154. package/src/gate/event-gate.ts +297 -9
  155. package/src/gate/gate-script-worker.ts +73 -0
  156. package/src/gate/gate-script.ts +180 -0
  157. package/src/gate/types.ts +36 -3
  158. package/src/index.ts +12 -0
  159. package/src/mcpl/channel-registry.ts +331 -6
  160. package/src/mcpl/checkpoint-manager.ts +16 -0
  161. package/src/mcpl/conversation-router.ts +284 -0
  162. package/src/mcpl/feature-set-manager.ts +14 -1
  163. package/src/mcpl/index.ts +12 -0
  164. package/src/mcpl/push-handler.ts +1 -0
  165. package/src/mcpl/server-connection.ts +157 -224
  166. package/src/mcpl/transport.ts +307 -0
  167. package/src/mcpl/types.ts +49 -2
  168. package/src/module-registry.ts +25 -2
  169. package/src/modules/discord/index.ts +93 -0
  170. package/src/prose-segments.ts +42 -0
  171. package/src/runtime/liveness-watchdog-worker.ts +66 -0
  172. package/src/runtime/liveness-watchdog.ts +122 -0
  173. package/src/tool-result-history.ts +57 -0
  174. package/src/types/agent.ts +21 -0
  175. package/src/types/framework.ts +24 -0
  176. package/src/types/module.ts +29 -0
  177. package/src/types/trace.ts +36 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Worker that runs the agent-authored `gate.js` decision function.
3
+ *
4
+ * The agent is trusted (it already has shell + filesystem), so this is NOT a
5
+ * security sandbox — it's a *robustness* boundary: running the script on a
6
+ * separate thread lets the main thread time it out (Atomics.wait) so an
7
+ * accidental infinite loop degrades to "fall through to declarative policies"
8
+ * instead of freezing the agent's own event loop.
9
+ *
10
+ * Protocol:
11
+ * - on startup we import `gate.js` and post `{ type: 'ready', error? }`.
12
+ * - per event the parent posts `{ type: 'eval', event }`; we run the script
13
+ * and write the JSON result into the shared buffer, flip the control word,
14
+ * and notify. The parent is blocked in Atomics.wait until then (or times out).
15
+ *
16
+ * `gate.js` shape (ESM): `export default (event) => behavior | null` where
17
+ * behavior is a GateBehavior ('always' | 'defer' | { debounce } | …) and null
18
+ * means "let the declarative gate.json policies decide". Sync or async.
19
+ */
20
+ import { parentPort, workerData } from 'node:worker_threads';
21
+ import { pathToFileURL } from 'node:url';
22
+ const { scriptPath, sab } = workerData;
23
+ const ctrl = new Int32Array(sab, 0, 2); // [0]=status (0 pending, 1 done), [1]=result byte length
24
+ const data = new Uint8Array(sab, 8);
25
+ const enc = new TextEncoder();
26
+ let fn = null;
27
+ // Load eagerly and announce readiness, so the parent doesn't time out (and
28
+ // pointlessly respawn) while a cold dynamic import is still in flight.
29
+ void (async () => {
30
+ let error = null;
31
+ try {
32
+ const mod = (await import(pathToFileURL(scriptPath).href));
33
+ const f = (mod.default ?? mod.decide ?? mod.gate);
34
+ if (typeof f !== 'function') {
35
+ error = 'gate.js must export a default function: (event) => behavior | null';
36
+ }
37
+ else {
38
+ fn = f;
39
+ }
40
+ }
41
+ catch (e) {
42
+ error = e?.message ?? String(e);
43
+ }
44
+ parentPort?.postMessage({ type: 'ready', error });
45
+ })();
46
+ function writeResult(obj) {
47
+ const bytes = enc.encode(JSON.stringify(obj));
48
+ const n = Math.min(bytes.length, data.length);
49
+ data.set(bytes.subarray(0, n));
50
+ Atomics.store(ctrl, 1, n);
51
+ Atomics.store(ctrl, 0, 1);
52
+ Atomics.notify(ctrl, 0);
53
+ }
54
+ parentPort?.on('message', (msg) => {
55
+ if (msg?.type !== 'eval')
56
+ return;
57
+ void (async () => {
58
+ if (!fn)
59
+ return writeResult({ behavior: null }); // load failed → fall through
60
+ try {
61
+ const r = await fn(msg.event); // sync OR async decision functions
62
+ writeResult({ behavior: r ?? null });
63
+ }
64
+ catch (e) {
65
+ writeResult({ error: e?.message ?? String(e) });
66
+ }
67
+ })();
68
+ });
69
+ //# sourceMappingURL=gate-script-worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-script-worker.js","sourceRoot":"","sources":["../../../src/gate/gate-script-worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAMzC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,UAAwB,CAAC;AACrD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,yDAAyD;AACjG,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACpC,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAG9B,IAAI,EAAE,GAAoB,IAAI,CAAC;AAE/B,2EAA2E;AAC3E,uEAAuE;AACvE,KAAK,CAAC,KAAK,IAAI,EAAE;IACf,IAAI,KAAK,GAAkB,IAAI,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAA4B,CAAC;QACtF,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,CAAY,CAAC;QAC7D,IAAI,OAAO,CAAC,KAAK,UAAU,EAAE,CAAC;YAC5B,KAAK,GAAG,oEAAoE,CAAC;QAC/E,CAAC;aAAM,CAAC;YACN,EAAE,GAAG,CAAa,CAAC;QACrB,CAAC;IACH,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,KAAK,GAAI,CAAW,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,UAAU,EAAE,WAAW,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AACpD,CAAC,CAAC,EAAE,CAAC;AAEL,SAAS,WAAW,CAAC,GAAY;IAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC9C,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/B,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,UAAU,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,GAAuC,EAAE,EAAE;IACpE,IAAI,GAAG,EAAE,IAAI,KAAK,MAAM;QAAE,OAAO;IACjC,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,IAAI,CAAC,EAAE;YAAE,OAAO,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,6BAA6B;QAC9E,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,mCAAmC;YAClE,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,WAAW,CAAC,EAAE,KAAK,EAAG,CAAW,EAAE,OAAO,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;AACP,CAAC,CAAC,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { GateBehavior, GateEventInfo } from './types.js';
2
+ export interface GateScriptStatus {
3
+ active: boolean;
4
+ ready: boolean;
5
+ path: string;
6
+ runs: number;
7
+ errors: number;
8
+ timeouts: number;
9
+ lastError: string | null;
10
+ }
11
+ export declare class GateScript {
12
+ private readonly scriptPath;
13
+ private readonly timeoutMs;
14
+ private readonly now;
15
+ private worker?;
16
+ private readonly sab;
17
+ private readonly ctrl;
18
+ private readonly data;
19
+ private readonly dec;
20
+ private mtime;
21
+ private lastCheck;
22
+ private active;
23
+ private ready;
24
+ private lastError;
25
+ private runs;
26
+ private errors;
27
+ private timeouts;
28
+ constructor(scriptPath: string, timeoutMs?: number, now?: () => number);
29
+ /** Hot-reload: (re)spawn the worker when gate.js appears or changes; stop it
30
+ * when the file is removed. Throttled like the gate's config reload. */
31
+ private reloadIfChanged;
32
+ private spawn;
33
+ private stop;
34
+ /**
35
+ * Evaluate the script for one event.
36
+ * - returns a GateBehavior → the script decided
37
+ * - returns null → fall through to the declarative policies
38
+ * - returns undefined → script inactive / errored / timed out (fall through)
39
+ */
40
+ evaluate(event: GateEventInfo): GateBehavior | null | undefined;
41
+ status(): GateScriptStatus;
42
+ dispose(): void;
43
+ }
44
+ //# sourceMappingURL=gate-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-script.d.ts","sourceRoot":"","sources":["../../../src/gate/gate-script.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAM9D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAOD,qBAAa,UAAU;IAgBnB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IAjBtB,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAmC;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAkC;IACvD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA+B;IACpD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,KAAK,CAAK;IAClB,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,IAAI,CAAK;IACjB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAK;gBAGF,UAAU,EAAE,MAAM,EAClB,SAAS,SAAK,EACd,GAAG,GAAE,MAAM,MAAiB;IAK/C;6EACyE;IACzE,OAAO,CAAC,eAAe;IAmBvB,OAAO,CAAC,KAAK;IAyBb,OAAO,CAAC,IAAI;IASZ;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,YAAY,GAAG,IAAI,GAAG,SAAS;IAwC/D,MAAM,IAAI,gBAAgB;IAY1B,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * GateScript — runs an agent-authored `gate.js` decision function on a worker
3
+ * thread, synchronously from the gate's perspective, with a hard timeout.
4
+ *
5
+ * The agent is trusted (shell + fs already), so this is a robustness seatbelt,
6
+ * not a security sandbox: a script that throws falls through to the declarative
7
+ * policies (and the error is surfaced via status()); a script that hangs is
8
+ * timed out (Atomics.wait), the wedged worker is terminated and respawned, and
9
+ * the event falls through — so a bad rule can't brick the agent's own attention.
10
+ *
11
+ * Sync model: the main thread posts the event then blocks in Atomics.wait until
12
+ * the worker writes the result into shared memory (or the timeout elapses).
13
+ * Node permits Atomics.wait on the main thread, so evaluate() stays synchronous
14
+ * and the rest of the EventGate is unchanged.
15
+ */
16
+ import { Worker } from 'node:worker_threads';
17
+ import { existsSync, statSync } from 'node:fs';
18
+ import { fileURLToPath } from 'node:url';
19
+ import { dirname, join } from 'node:path';
20
+ const WORKER_PATH = join(dirname(fileURLToPath(import.meta.url)), 'gate-script-worker.js');
21
+ const SAB_SIZE = 16_384;
22
+ const RELOAD_THROTTLE_MS = 1000;
23
+ export class GateScript {
24
+ scriptPath;
25
+ timeoutMs;
26
+ now;
27
+ worker;
28
+ sab = new SharedArrayBuffer(SAB_SIZE);
29
+ ctrl = new Int32Array(this.sab, 0, 2);
30
+ data = new Uint8Array(this.sab, 8);
31
+ dec = new TextDecoder();
32
+ mtime = 0;
33
+ lastCheck = 0;
34
+ active = false;
35
+ ready = false;
36
+ lastError = null;
37
+ runs = 0;
38
+ errors = 0;
39
+ timeouts = 0;
40
+ constructor(scriptPath, timeoutMs = 50, now = Date.now) {
41
+ this.scriptPath = scriptPath;
42
+ this.timeoutMs = timeoutMs;
43
+ this.now = now;
44
+ this.reloadIfChanged();
45
+ }
46
+ /** Hot-reload: (re)spawn the worker when gate.js appears or changes; stop it
47
+ * when the file is removed. Throttled like the gate's config reload. */
48
+ reloadIfChanged() {
49
+ const t = this.now();
50
+ if (this.lastCheck !== 0 && t - this.lastCheck < RELOAD_THROTTLE_MS)
51
+ return;
52
+ this.lastCheck = t;
53
+ if (!existsSync(this.scriptPath)) {
54
+ if (this.active)
55
+ this.stop();
56
+ return;
57
+ }
58
+ let m = 0;
59
+ try {
60
+ m = statSync(this.scriptPath).mtimeMs;
61
+ }
62
+ catch {
63
+ return;
64
+ }
65
+ if (this.active && m === this.mtime)
66
+ return;
67
+ this.mtime = m;
68
+ this.spawn();
69
+ }
70
+ spawn() {
71
+ this.stop();
72
+ try {
73
+ const w = new Worker(WORKER_PATH, {
74
+ workerData: { scriptPath: this.scriptPath, sab: this.sab },
75
+ });
76
+ w.on('message', (m) => {
77
+ if (m?.type === 'ready') {
78
+ this.ready = true; // load finished (with or without a load error)
79
+ if (m.error)
80
+ this.lastError = m.error;
81
+ }
82
+ });
83
+ w.on('error', (e) => {
84
+ this.lastError = e.message;
85
+ });
86
+ w.unref(); // never keep the process alive on the gate script's account
87
+ this.worker = w;
88
+ this.active = true;
89
+ this.lastError = null;
90
+ }
91
+ catch (e) {
92
+ this.lastError = e.message;
93
+ this.active = false;
94
+ }
95
+ }
96
+ stop() {
97
+ if (this.worker) {
98
+ void this.worker.terminate().catch(() => { });
99
+ this.worker = undefined;
100
+ }
101
+ this.active = false;
102
+ this.ready = false;
103
+ }
104
+ /**
105
+ * Evaluate the script for one event.
106
+ * - returns a GateBehavior → the script decided
107
+ * - returns null → fall through to the declarative policies
108
+ * - returns undefined → script inactive / errored / timed out (fall through)
109
+ */
110
+ evaluate(event) {
111
+ this.reloadIfChanged();
112
+ // Inactive, or the worker hasn't finished importing gate.js yet → fall
113
+ // through (don't time-out/respawn during a cold start).
114
+ if (!this.active || !this.worker || !this.ready)
115
+ return undefined;
116
+ Atomics.store(this.ctrl, 0, 0);
117
+ try {
118
+ this.worker.postMessage({ type: 'eval', event });
119
+ }
120
+ catch (e) {
121
+ this.lastError = e.message;
122
+ return undefined;
123
+ }
124
+ const r = Atomics.wait(this.ctrl, 0, 0, this.timeoutMs);
125
+ this.runs++;
126
+ if (r === 'timed-out') {
127
+ this.timeouts++;
128
+ this.lastError = `gate.js timed out (>${this.timeoutMs}ms) — terminated and restarted`;
129
+ this.spawn(); // kill the wedged worker, fresh one for next time
130
+ return undefined;
131
+ }
132
+ const len = Atomics.load(this.ctrl, 1);
133
+ let parsed;
134
+ try {
135
+ parsed = JSON.parse(this.dec.decode(this.data.subarray(0, len)));
136
+ }
137
+ catch {
138
+ this.errors++;
139
+ this.lastError = 'gate.js produced an unreadable result';
140
+ return undefined;
141
+ }
142
+ if (parsed.error) {
143
+ this.errors++;
144
+ this.lastError = parsed.error;
145
+ return undefined;
146
+ }
147
+ return parsed.behavior ?? null;
148
+ }
149
+ status() {
150
+ return {
151
+ active: this.active,
152
+ ready: this.ready,
153
+ path: this.scriptPath,
154
+ runs: this.runs,
155
+ errors: this.errors,
156
+ timeouts: this.timeouts,
157
+ lastError: this.lastError,
158
+ };
159
+ }
160
+ dispose() {
161
+ this.stop();
162
+ }
163
+ }
164
+ //# sourceMappingURL=gate-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate-script.js","sourceRoot":"","sources":["../../../src/gate/gate-script.ts"],"names":[],"mappings":"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"}
@@ -43,7 +43,7 @@ export interface PassiveSampleConfig {
43
43
  keyBy?: string;
44
44
  }
45
45
  /** How a matching policy affects inference triggering. */
46
- export type GateBehavior = 'always' | 'skip' | {
46
+ export type GateBehavior = 'always' | 'defer' | 'skip' | {
47
47
  debounce: number;
48
48
  } | {
49
49
  rate_limit: RateLimitConfig;
@@ -80,6 +80,17 @@ export interface GatePolicyMatch {
80
80
  * matches if any of those is set. Empty/omitted = no metadata constraint.
81
81
  */
82
82
  metadataTrue?: string[];
83
+ /**
84
+ * Tag matching (MCPL RFC-001 event tags). Globs allowed (e.g. `robotics:*`).
85
+ * Evaluated against the event's (implication-expanded) tag set:
86
+ * tagsAny — match if ANY listed pattern matches an event tag
87
+ * tagsAll — match only if EVERY listed pattern matches some event tag
88
+ * tagsNone — match only if NO listed pattern matches any event tag
89
+ * Combined with the other fields by AND, like the rest of the match.
90
+ */
91
+ tagsAny?: string[];
92
+ tagsAll?: string[];
93
+ tagsNone?: string[];
83
94
  }
84
95
  /** A single gate policy — one rule in the ordered policy list. */
85
96
  export interface GatePolicy {
@@ -98,7 +109,7 @@ export interface GatePolicy {
98
109
  export interface GateConfig {
99
110
  policies: GatePolicy[];
100
111
  /** Behavior when no policy matches. Default: 'always'. */
101
- default?: 'always' | 'skip';
112
+ default?: 'always' | 'defer' | 'skip';
102
113
  }
103
114
  /** Options for configuring the EventGate via FrameworkConfig. */
104
115
  export interface GateOptions {
@@ -106,6 +117,13 @@ export interface GateOptions {
106
117
  configPath?: string;
107
118
  /** Initial config, seeded to gate.json if the file doesn't exist. */
108
119
  config?: GateConfig;
120
+ /**
121
+ * Path to a JSON file listing user ids that may wake the agent even while
122
+ * it is asleep (`sleep` tool). The file is either a bare array of id
123
+ * strings or `{ "userIds": [...] }`. Hot-reloaded on change. When unset or
124
+ * missing, no one bypasses sleep.
125
+ */
126
+ privilegedUsersPath?: string;
109
127
  }
110
128
  /** The result of evaluating an event against the gate. */
111
129
  export interface GateDecision {
@@ -127,6 +145,8 @@ export interface GateEventInfo {
127
145
  mount?: string;
128
146
  /** Mount-prefixed paths touched (for workspace:* events). */
129
147
  paths?: string[];
148
+ /** Event tags (MCPL RFC-001), already implication-expanded by the host. */
149
+ tags?: string[];
130
150
  }
131
151
  /** Per-policy runtime statistics (for gate:status). */
132
152
  export interface GatePolicyStats {
@@ -154,7 +174,9 @@ export interface GateStatus {
154
174
  configPath: string;
155
175
  configSource: 'file' | 'initial' | 'default';
156
176
  lastReloadTimestamp: number | null;
157
- default: 'always' | 'skip';
177
+ default: 'always' | 'defer' | 'skip';
178
+ /** Status of the optional programmable gate (gate.js). */
179
+ script: import('./gate-script.js').GateScriptStatus;
158
180
  policies: GatePolicyStats[];
159
181
  errors: string[];
160
182
  /** Total events the gate has evaluated since startup. */
@@ -174,5 +196,15 @@ export interface GateStatus {
174
196
  skipped: number;
175
197
  }>;
176
198
  };
199
+ /** Present when the agent is currently asleep (sleep tool). */
200
+ sleep?: {
201
+ until: number;
202
+ remainingMs: number;
203
+ note?: string;
204
+ /** How many wake events have been suppressed during the current sleep. */
205
+ suppressed: number;
206
+ /** Count of privileged user ids that may wake through sleep. */
207
+ privilegedCount: number;
208
+ };
177
209
  }
178
210
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/gate/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/gate/types.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,8 @@ export type { SessionUsage, AgentUsage, SessionUsageSnapshot, UsageUpdatedEvent
13
13
  export { EventGate } from './gate/index.js';
14
14
  export type { GateConfig, GateOptions, GatePolicy, GatePolicyMatch, GateBehavior } from './gate/index.js';
15
15
  export { ChannelRegistry } from './mcpl/index.js';
16
+ export { ConversationRouter, DEFAULT_CLOSURE_PROMPT } from './mcpl/index.js';
17
+ export type { ConversationRouterConfig, ConversationBinding, RoutingDecision, IncomingMessageFacts, BindRule, TriggerRule, ChannelKind, } from './mcpl/index.js';
16
18
  export type { ContextManager, ContextStrategy, TokenBudget } from '@animalabs/context-manager';
17
19
  export { PassthroughStrategy, AutobiographicalStrategy, KnowledgeStrategy } from '@animalabs/context-manager';
18
20
  export type { KnowledgeConfig, PhaseType } from '@animalabs/context-manager';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,YAAY,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1G,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG1G,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC9G,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC7E,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,cAAc,oBAAoB,CAAC;AAGnC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAChD,YAAY,EACV,eAAe,EACf,UAAU,EACV,UAAU,EACV,WAAW,EACX,QAAQ,EACR,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAKxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAG1G,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG1G,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,YAAY,EACV,wBAAwB,EACxB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,QAAQ,EACR,WAAW,EACX,WAAW,GACZ,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC9G,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC7E,YAAY,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/src/index.js CHANGED
@@ -18,5 +18,7 @@ export { UsageTracker } from './usage/index.js';
18
18
  export { EventGate } from './gate/index.js';
19
19
  // MCPL channel registry (exposed for modules that need channel-level operations)
20
20
  export { ChannelRegistry } from './mcpl/index.js';
21
+ // Per-channel conversation routing
22
+ export { ConversationRouter, DEFAULT_CLOSURE_PROMPT } from './mcpl/index.js';
21
23
  export { PassthroughStrategy, AutobiographicalStrategy, KnowledgeStrategy } from '@animalabs/context-manager';
22
24
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,kBAAkB,CAAC;AAEjC,eAAe;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,mBAAmB;AACnB,cAAc,oBAAoB,CAAC;AAEnC,MAAM;AACN,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAoChD,yFAAyF;AACzF,6DAA6D;AAE7D,iBAAiB;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,YAAY;AACZ,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIlD,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,cAAc,kBAAkB,CAAC;AAEjC,eAAe;AACf,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,mBAAmB;AACnB,cAAc,oBAAoB,CAAC;AAEnC,MAAM;AACN,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAoChD,yFAAyF;AACzF,6DAA6D;AAE7D,iBAAiB;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGhD,YAAY;AACZ,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,iFAAiF;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,mCAAmC;AACnC,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAa7E,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -30,6 +30,45 @@ interface Responder {
30
30
  interface ChannelRegistryOptions {
31
31
  /** Callback to determine whether an incoming message should trigger inference. */
32
32
  shouldTriggerInference?: (content: string, metadata: Record<string, unknown>) => boolean;
33
+ /**
34
+ * Called when a text-only turn's speech could NOT be delivered to its
35
+ * conversational locus — no locus, an unregistered channel, a missing
36
+ * server, or the server reporting `delivered: false`. The host wires this
37
+ * to drop a `[discord-send-failed]` marker into chronicle so the failure is
38
+ * visible to the agent (and operator) rather than silently lost. Must not
39
+ * itself trigger inference (avoid wake loops).
40
+ */
41
+ onRouteFailure?: (info: {
42
+ conversationId: string;
43
+ channelId: string | null;
44
+ reason: string;
45
+ textLen: number;
46
+ }) => void;
47
+ /**
48
+ * Resolve a conversation fork's HOME channel from its agent name. Conversation
49
+ * forks are spawned bound to a single channel (the framework tracks this in
50
+ * `conversationAgentHomes` / `ConversationRouter.channelForAgent`); their
51
+ * plain-text speech must route THERE. The process-global `defaultPublishChannel`
52
+ * tracks only the most-recent inbound across ALL channels, so with one fork per
53
+ * channel running concurrently it misroutes a fork's reply to whichever channel
54
+ * last spoke (item 3). Returns undefined for the trunk/primary agent, which has
55
+ * no home and correctly falls back to the global locus (heartbeats, etc.).
56
+ */
57
+ homeChannelResolver?: (agentName: string) => string | undefined;
58
+ /**
59
+ * Resolve the channel that triggered an agent's CURRENT inference turn, by
60
+ * agent name. This is the fix for single-TRUNK agents (the only mode
61
+ * connectome-host runs — it never exposes conversation forks). A trunk agent
62
+ * has no fork home, so without this its plain-text speech falls back to the
63
+ * process-global `defaultPublishChannel`, which tracks the most-recent inbound
64
+ * across ALL channels and misroutes a reply to whichever channel last spoke
65
+ * under concurrency (item-3 redux). The framework tracks the triggering
66
+ * channel of the live turn per-agent and exposes it here; resolves to
67
+ * undefined for a heartbeat / no-trigger turn, which correctly keeps the
68
+ * global fallback. Consulted AFTER `homeChannelResolver` (a fork's home always
69
+ * wins), BEFORE `defaultPublishChannel`.
70
+ */
71
+ activeChannelResolver?: (agentName: string) => string | undefined;
33
72
  }
34
73
  export declare class ChannelRegistry {
35
74
  private serverRegistry;
@@ -38,6 +77,9 @@ export declare class ChannelRegistry {
38
77
  private emitTraceFn;
39
78
  private sendTypingFn?;
40
79
  private shouldTriggerInference?;
80
+ private onRouteFailure?;
81
+ private homeChannelResolver?;
82
+ private activeChannelResolver?;
41
83
  /** Registered channels, keyed by `{serverId}:{channelId}`. */
42
84
  private channels;
43
85
  /** Most recent incoming channel ID — used for speech routing / default publish. */
@@ -87,6 +129,21 @@ export declare class ChannelRegistry {
87
129
  * queue, and responds with per-message results.
88
130
  */
89
131
  handleIncoming(serverId: string, params: ChannelsIncomingParams, responder?: Responder): void;
132
+ /**
133
+ * Ensure a channel is registered AND open so it can serve as an outbound
134
+ * routing locus, lazy-registering it if unseen and opening it if closed.
135
+ *
136
+ * Mirrors the lazy-registration inside handleIncoming(), but for channels
137
+ * that only ever arrive as push/events rather than channels/incoming — the
138
+ * motivating case is Discord DMs, which discord-mcpl forwards via push/event
139
+ * with the channel closed (`channelIsOpen:false`). Such a channel is never
140
+ * registered, so routeSpeech() can't resolve it and the agent's reply is
141
+ * silently dropped even though the inbound message proves the channel is
142
+ * reachable (item-3 redux, DM sub-case). Idempotent: a later authoritative
143
+ * channels/register or channels/changed overwrites this descriptor with the
144
+ * richer one; re-opening an already-open channel is a no-op.
145
+ */
146
+ ensureChannelRegistered(serverId: string, channelId: string, label?: string): void;
90
147
  /**
91
148
  * Start sending typing indicators for a channel.
92
149
  *
@@ -107,6 +164,11 @@ export declare class ChannelRegistry {
107
164
  * Get the default publish channel ID (most recent incoming channel).
108
165
  */
109
166
  getDefaultPublishChannel(): string | null;
167
+ /**
168
+ * Get the descriptor for a channel by its channelId (first match across
169
+ * servers). Used by the conversation router for DM classification.
170
+ */
171
+ getDescriptor(channelId: string): ChannelDescriptor | undefined;
110
172
  /**
111
173
  * Get all open channels.
112
174
  */
@@ -124,7 +186,7 @@ export declare class ChannelRegistry {
124
186
  *
125
187
  * Returns undefined if no channels are active.
126
188
  */
127
- buildChannelContext(): ChannelContext | undefined;
189
+ buildChannelContext(agentName?: string): ChannelContext | undefined;
128
190
  /**
129
191
  * Stop all typing intervals and clear all channel registrations.
130
192
  */
@@ -137,6 +199,8 @@ export declare class ChannelRegistry {
137
199
  * (typing timer lifecycle is still managed for when the callback is wired).
138
200
  */
139
201
  private sendTypingNotification;
202
+ /** Server id owning a registered channel (by descriptor id), or null. */
203
+ getChannelServerId(channelId: string): string | null;
140
204
  /**
141
205
  * Find a channel entry by channelId (searches across all servers).
142
206
  * Returns the first match.
@@ -149,6 +213,34 @@ export declare class ChannelRegistry {
149
213
  private handleToolList;
150
214
  private handleToolOpen;
151
215
  private handleToolClose;
216
+ /**
217
+ * Handle the synthesized `think` tool — a private reasoning scratchpad. It
218
+ * sends nothing, and (unlike before) does NOT silence the turn: trailing
219
+ * plain text is still routed as the reply. The thought stays in the agent's
220
+ * own context/chronicle. To deliberately not reply, the agent uses skip_reply.
221
+ */
222
+ private handleToolThink;
223
+ /**
224
+ * Handle the synthesized `skip_reply` tool — the deliberate "stay silent"
225
+ * signal. A no-op as far as any surface is concerned (sends nothing); its
226
+ * effect is that the framework's output routing treats this as a silencing
227
+ * tool, so any trailing prose this turn is NOT posted. Replaces the old
228
+ * overloaded use of `think` for staying silent.
229
+ */
230
+ private handleToolSkipReply;
231
+ /**
232
+ * Host-owned output routing (see forking-knowledge-miner LOCUS-ROUTING-DESIGN).
233
+ * Publish the agent's plain-text speech to the current conversational locus
234
+ * (the most recent incoming channel, tracked cross-surface here in the host).
235
+ * Called by the framework on a text-only turn — replaces the per-surface
236
+ * sticky auto-post that used to live in discord-mcpl. Returns null when there
237
+ * is no locus / the channel or its server can't be resolved (in which case
238
+ * the speech simply stays in chronicle + module surfaces).
239
+ */
240
+ routeSpeech(conversationId: string, text: string): Promise<{
241
+ delivered: boolean;
242
+ channelId: string;
243
+ } | null>;
152
244
  private handleToolPublish;
153
245
  }
154
246
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"channel-registry.d.ts","sourceRoot":"","sources":["../../../src/mcpl/channel-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel-registry.d.ts","sourceRoot":"","sources":["../../../src/mcpl/channel-registry.ts"],"names":[],"mappings":"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"}