@darkiceinteractive/mcp-conductor 2.0.0-alpha.1 → 3.0.0-beta.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.
Files changed (276) hide show
  1. package/README.md +35 -5
  2. package/dist/bin/cli.d.ts +20 -0
  3. package/dist/bin/cli.d.ts.map +1 -0
  4. package/dist/bin/cli.js +260 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/bridge/http-server.d.ts +35 -0
  7. package/dist/bridge/http-server.d.ts.map +1 -1
  8. package/dist/bridge/http-server.js +51 -2
  9. package/dist/bridge/http-server.js.map +1 -1
  10. package/dist/bridge/index.d.ts +1 -0
  11. package/dist/bridge/index.d.ts.map +1 -1
  12. package/dist/bridge/index.js +1 -0
  13. package/dist/bridge/index.js.map +1 -1
  14. package/dist/bridge/pool.d.ts +95 -0
  15. package/dist/bridge/pool.d.ts.map +1 -0
  16. package/dist/bridge/pool.js +384 -0
  17. package/dist/bridge/pool.js.map +1 -0
  18. package/dist/cache/cache.d.ts +64 -0
  19. package/dist/cache/cache.d.ts.map +1 -0
  20. package/dist/cache/cache.js +209 -0
  21. package/dist/cache/cache.js.map +1 -0
  22. package/dist/cache/delta.d.ts +32 -0
  23. package/dist/cache/delta.d.ts.map +1 -0
  24. package/dist/cache/delta.js +131 -0
  25. package/dist/cache/delta.js.map +1 -0
  26. package/dist/cache/disk.d.ts +65 -0
  27. package/dist/cache/disk.d.ts.map +1 -0
  28. package/dist/cache/disk.js +238 -0
  29. package/dist/cache/disk.js.map +1 -0
  30. package/dist/cache/index.d.ts +53 -0
  31. package/dist/cache/index.d.ts.map +1 -0
  32. package/dist/cache/index.js +12 -0
  33. package/dist/cache/index.js.map +1 -0
  34. package/dist/cache/key.d.ts +44 -0
  35. package/dist/cache/key.d.ts.map +1 -0
  36. package/dist/cache/key.js +83 -0
  37. package/dist/cache/key.js.map +1 -0
  38. package/dist/cache/lru.d.ts +57 -0
  39. package/dist/cache/lru.d.ts.map +1 -0
  40. package/dist/cache/lru.js +112 -0
  41. package/dist/cache/lru.js.map +1 -0
  42. package/dist/cache/policy.d.ts +34 -0
  43. package/dist/cache/policy.d.ts.map +1 -0
  44. package/dist/cache/policy.js +95 -0
  45. package/dist/cache/policy.js.map +1 -0
  46. package/dist/cli/commands/doctor.d.ts +33 -0
  47. package/dist/cli/commands/doctor.d.ts.map +1 -0
  48. package/dist/cli/commands/doctor.js +135 -0
  49. package/dist/cli/commands/doctor.js.map +1 -0
  50. package/dist/cli/commands/export-servers.d.ts +22 -0
  51. package/dist/cli/commands/export-servers.d.ts.map +1 -0
  52. package/dist/cli/commands/export-servers.js +45 -0
  53. package/dist/cli/commands/export-servers.js.map +1 -0
  54. package/dist/cli/commands/import-servers.d.ts +57 -0
  55. package/dist/cli/commands/import-servers.d.ts.map +1 -0
  56. package/dist/cli/commands/import-servers.js +137 -0
  57. package/dist/cli/commands/import-servers.js.map +1 -0
  58. package/dist/cli/commands/routing.d.ts +34 -0
  59. package/dist/cli/commands/routing.d.ts.map +1 -0
  60. package/dist/cli/commands/routing.js +60 -0
  61. package/dist/cli/commands/routing.js.map +1 -0
  62. package/dist/cli/commands/test-server.d.ts +34 -0
  63. package/dist/cli/commands/test-server.d.ts.map +1 -0
  64. package/dist/cli/commands/test-server.js +86 -0
  65. package/dist/cli/commands/test-server.js.map +1 -0
  66. package/dist/cli/daemon.d.ts +60 -0
  67. package/dist/cli/daemon.d.ts.map +1 -0
  68. package/dist/cli/daemon.js +244 -0
  69. package/dist/cli/daemon.js.map +1 -0
  70. package/dist/cli/replay.d.ts +16 -0
  71. package/dist/cli/replay.d.ts.map +1 -0
  72. package/dist/cli/replay.js +89 -0
  73. package/dist/cli/replay.js.map +1 -0
  74. package/dist/cli/wizard/setup.d.ts +12 -0
  75. package/dist/cli/wizard/setup.d.ts.map +1 -0
  76. package/dist/cli/wizard/setup.js +71 -0
  77. package/dist/cli/wizard/setup.js.map +1 -0
  78. package/dist/config/defaults.d.ts.map +1 -1
  79. package/dist/config/defaults.js +4 -1
  80. package/dist/config/defaults.js.map +1 -1
  81. package/dist/config/schema.d.ts +34 -0
  82. package/dist/config/schema.d.ts.map +1 -1
  83. package/dist/daemon/client.d.ts +99 -0
  84. package/dist/daemon/client.d.ts.map +1 -0
  85. package/dist/daemon/client.js +292 -0
  86. package/dist/daemon/client.js.map +1 -0
  87. package/dist/daemon/discovery.d.ts +50 -0
  88. package/dist/daemon/discovery.d.ts.map +1 -0
  89. package/dist/daemon/discovery.js +104 -0
  90. package/dist/daemon/discovery.js.map +1 -0
  91. package/dist/daemon/index.d.ts +16 -0
  92. package/dist/daemon/index.d.ts.map +1 -0
  93. package/dist/daemon/index.js +11 -0
  94. package/dist/daemon/index.js.map +1 -0
  95. package/dist/daemon/sandbox-api.d.ts +45 -0
  96. package/dist/daemon/sandbox-api.d.ts.map +1 -0
  97. package/dist/daemon/sandbox-api.js +74 -0
  98. package/dist/daemon/sandbox-api.js.map +1 -0
  99. package/dist/daemon/server.d.ts +65 -0
  100. package/dist/daemon/server.d.ts.map +1 -0
  101. package/dist/daemon/server.js +373 -0
  102. package/dist/daemon/server.js.map +1 -0
  103. package/dist/daemon/shared-kv.d.ts +81 -0
  104. package/dist/daemon/shared-kv.d.ts.map +1 -0
  105. package/dist/daemon/shared-kv.js +215 -0
  106. package/dist/daemon/shared-kv.js.map +1 -0
  107. package/dist/daemon/shared-lock.d.ts +71 -0
  108. package/dist/daemon/shared-lock.d.ts.map +1 -0
  109. package/dist/daemon/shared-lock.js +119 -0
  110. package/dist/daemon/shared-lock.js.map +1 -0
  111. package/dist/hub/mcp-hub.d.ts +23 -0
  112. package/dist/hub/mcp-hub.d.ts.map +1 -1
  113. package/dist/hub/mcp-hub.js +34 -1
  114. package/dist/hub/mcp-hub.js.map +1 -1
  115. package/dist/index.js +7 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/observability/anomaly.d.ts +67 -0
  118. package/dist/observability/anomaly.d.ts.map +1 -0
  119. package/dist/observability/anomaly.js +141 -0
  120. package/dist/observability/anomaly.js.map +1 -0
  121. package/dist/observability/cost-predictor.d.ts +49 -0
  122. package/dist/observability/cost-predictor.d.ts.map +1 -0
  123. package/dist/observability/cost-predictor.js +145 -0
  124. package/dist/observability/cost-predictor.js.map +1 -0
  125. package/dist/observability/hot-path.d.ts +49 -0
  126. package/dist/observability/hot-path.d.ts.map +1 -0
  127. package/dist/observability/hot-path.js +125 -0
  128. package/dist/observability/hot-path.js.map +1 -0
  129. package/dist/observability/index.d.ts +10 -0
  130. package/dist/observability/index.d.ts.map +1 -0
  131. package/dist/observability/index.js +10 -0
  132. package/dist/observability/index.js.map +1 -0
  133. package/dist/observability/replay.d.ts +104 -0
  134. package/dist/observability/replay.d.ts.map +1 -0
  135. package/dist/observability/replay.js +239 -0
  136. package/dist/observability/replay.js.map +1 -0
  137. package/dist/registry/built-in-recommendations.d.ts +54 -0
  138. package/dist/registry/built-in-recommendations.d.ts.map +1 -0
  139. package/dist/registry/built-in-recommendations.js +65 -0
  140. package/dist/registry/built-in-recommendations.js.map +1 -0
  141. package/dist/registry/events.d.ts +26 -0
  142. package/dist/registry/events.d.ts.map +1 -0
  143. package/dist/registry/events.js +22 -0
  144. package/dist/registry/events.js.map +1 -0
  145. package/dist/registry/index.d.ts +159 -0
  146. package/dist/registry/index.d.ts.map +1 -0
  147. package/dist/registry/index.js +12 -0
  148. package/dist/registry/index.js.map +1 -0
  149. package/dist/registry/registry.d.ts +87 -0
  150. package/dist/registry/registry.d.ts.map +1 -0
  151. package/dist/registry/registry.js +294 -0
  152. package/dist/registry/registry.js.map +1 -0
  153. package/dist/registry/snapshot.d.ts +42 -0
  154. package/dist/registry/snapshot.d.ts.map +1 -0
  155. package/dist/registry/snapshot.js +71 -0
  156. package/dist/registry/snapshot.js.map +1 -0
  157. package/dist/registry/typegen.d.ts +48 -0
  158. package/dist/registry/typegen.d.ts.map +1 -0
  159. package/dist/registry/typegen.js +200 -0
  160. package/dist/registry/typegen.js.map +1 -0
  161. package/dist/registry/validator.d.ts +23 -0
  162. package/dist/registry/validator.d.ts.map +1 -0
  163. package/dist/registry/validator.js +50 -0
  164. package/dist/registry/validator.js.map +1 -0
  165. package/dist/reliability/breaker.d.ts +57 -0
  166. package/dist/reliability/breaker.d.ts.map +1 -0
  167. package/dist/reliability/breaker.js +130 -0
  168. package/dist/reliability/breaker.js.map +1 -0
  169. package/dist/reliability/errors.d.ts +78 -0
  170. package/dist/reliability/errors.d.ts.map +1 -0
  171. package/dist/reliability/errors.js +160 -0
  172. package/dist/reliability/errors.js.map +1 -0
  173. package/dist/reliability/gateway.d.ts +88 -0
  174. package/dist/reliability/gateway.d.ts.map +1 -0
  175. package/dist/reliability/gateway.js +180 -0
  176. package/dist/reliability/gateway.js.map +1 -0
  177. package/dist/reliability/index.d.ts +20 -0
  178. package/dist/reliability/index.d.ts.map +1 -0
  179. package/dist/reliability/index.js +16 -0
  180. package/dist/reliability/index.js.map +1 -0
  181. package/dist/reliability/profile.d.ts +49 -0
  182. package/dist/reliability/profile.d.ts.map +1 -0
  183. package/dist/reliability/profile.js +58 -0
  184. package/dist/reliability/profile.js.map +1 -0
  185. package/dist/reliability/retry.d.ts +39 -0
  186. package/dist/reliability/retry.d.ts.map +1 -0
  187. package/dist/reliability/retry.js +51 -0
  188. package/dist/reliability/retry.js.map +1 -0
  189. package/dist/reliability/timeout.d.ts +34 -0
  190. package/dist/reliability/timeout.d.ts.map +1 -0
  191. package/dist/reliability/timeout.js +53 -0
  192. package/dist/reliability/timeout.js.map +1 -0
  193. package/dist/runtime/executor.d.ts.map +1 -1
  194. package/dist/runtime/executor.js +122 -14
  195. package/dist/runtime/executor.js.map +1 -1
  196. package/dist/runtime/findtool/embed.d.ts +28 -0
  197. package/dist/runtime/findtool/embed.d.ts.map +1 -0
  198. package/dist/runtime/findtool/embed.js +85 -0
  199. package/dist/runtime/findtool/embed.js.map +1 -0
  200. package/dist/runtime/findtool/index.d.ts +52 -0
  201. package/dist/runtime/findtool/index.d.ts.map +1 -0
  202. package/dist/runtime/findtool/index.js +78 -0
  203. package/dist/runtime/findtool/index.js.map +1 -0
  204. package/dist/runtime/findtool/vector-index.d.ts +53 -0
  205. package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
  206. package/dist/runtime/findtool/vector-index.js +71 -0
  207. package/dist/runtime/findtool/vector-index.js.map +1 -0
  208. package/dist/runtime/helpers/budget.d.ts +27 -0
  209. package/dist/runtime/helpers/budget.d.ts.map +1 -0
  210. package/dist/runtime/helpers/budget.js +103 -0
  211. package/dist/runtime/helpers/budget.js.map +1 -0
  212. package/dist/runtime/helpers/compact.d.ts +32 -0
  213. package/dist/runtime/helpers/compact.d.ts.map +1 -0
  214. package/dist/runtime/helpers/compact.js +93 -0
  215. package/dist/runtime/helpers/compact.js.map +1 -0
  216. package/dist/runtime/helpers/delta.d.ts +45 -0
  217. package/dist/runtime/helpers/delta.d.ts.map +1 -0
  218. package/dist/runtime/helpers/delta.js +116 -0
  219. package/dist/runtime/helpers/delta.js.map +1 -0
  220. package/dist/runtime/helpers/index.d.ts +16 -0
  221. package/dist/runtime/helpers/index.d.ts.map +1 -0
  222. package/dist/runtime/helpers/index.js +13 -0
  223. package/dist/runtime/helpers/index.js.map +1 -0
  224. package/dist/runtime/helpers/summarize.d.ts +24 -0
  225. package/dist/runtime/helpers/summarize.d.ts.map +1 -0
  226. package/dist/runtime/helpers/summarize.js +124 -0
  227. package/dist/runtime/helpers/summarize.js.map +1 -0
  228. package/dist/runtime/helpers/worker-preload.d.ts +25 -0
  229. package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
  230. package/dist/runtime/helpers/worker-preload.js +223 -0
  231. package/dist/runtime/helpers/worker-preload.js.map +1 -0
  232. package/dist/runtime/index.d.ts +1 -0
  233. package/dist/runtime/index.d.ts.map +1 -1
  234. package/dist/runtime/index.js +1 -0
  235. package/dist/runtime/index.js.map +1 -1
  236. package/dist/runtime/pool/index.d.ts +11 -0
  237. package/dist/runtime/pool/index.d.ts.map +1 -0
  238. package/dist/runtime/pool/index.js +8 -0
  239. package/dist/runtime/pool/index.js.map +1 -0
  240. package/dist/runtime/pool/recycle.d.ts +44 -0
  241. package/dist/runtime/pool/recycle.d.ts.map +1 -0
  242. package/dist/runtime/pool/recycle.js +50 -0
  243. package/dist/runtime/pool/recycle.js.map +1 -0
  244. package/dist/runtime/pool/worker-pool.d.ts +77 -0
  245. package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
  246. package/dist/runtime/pool/worker-pool.js +216 -0
  247. package/dist/runtime/pool/worker-pool.js.map +1 -0
  248. package/dist/runtime/pool/worker.d.ts +80 -0
  249. package/dist/runtime/pool/worker.d.ts.map +1 -0
  250. package/dist/runtime/pool/worker.js +324 -0
  251. package/dist/runtime/pool/worker.js.map +1 -0
  252. package/dist/server/mcp-server.d.ts +3 -0
  253. package/dist/server/mcp-server.d.ts.map +1 -1
  254. package/dist/server/mcp-server.js +457 -3
  255. package/dist/server/mcp-server.js.map +1 -1
  256. package/dist/server/passthrough-registrar.d.ts +123 -0
  257. package/dist/server/passthrough-registrar.d.ts.map +1 -0
  258. package/dist/server/passthrough-registrar.js +199 -0
  259. package/dist/server/passthrough-registrar.js.map +1 -0
  260. package/dist/skills/skills-engine.d.ts +9 -1
  261. package/dist/skills/skills-engine.d.ts.map +1 -1
  262. package/dist/skills/skills-engine.js +20 -3
  263. package/dist/skills/skills-engine.js.map +1 -1
  264. package/dist/utils/index.d.ts +1 -0
  265. package/dist/utils/index.d.ts.map +1 -1
  266. package/dist/utils/index.js +1 -0
  267. package/dist/utils/index.js.map +1 -1
  268. package/dist/utils/tokenize.d.ts +55 -0
  269. package/dist/utils/tokenize.d.ts.map +1 -0
  270. package/dist/utils/tokenize.js +205 -0
  271. package/dist/utils/tokenize.js.map +1 -0
  272. package/dist/version.d.ts +3 -3
  273. package/dist/version.d.ts.map +1 -1
  274. package/dist/version.js +3 -3
  275. package/dist/version.js.map +1 -1
  276. package/package.json +13 -3
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Observability module barrel
3
+ *
4
+ * Cost prediction, hot-path profiling, anomaly detection, and replay.
5
+ */
6
+ export * from './cost-predictor.js';
7
+ export * from './hot-path.js';
8
+ export * from './anomaly.js';
9
+ export * from './replay.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/observability/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Replay Recorder
3
+ *
4
+ * Records execute_code sessions to JSONL journals under
5
+ * ~/.mcp-conductor/recordings/. Supports deterministic replay with optional
6
+ * per-event modifications (replace or skip). Detects divergence when the
7
+ * replayed result differs from the recorded result.
8
+ *
9
+ * Journal line format (one JSON object per line):
10
+ * { "seq": <number>, "ts": <epoch-ms>, "type": "tool_call"|"tool_result"|"code_result",
11
+ * "server": <string>, "tool": <string>, "args": <object>, "result": <unknown> }
12
+ *
13
+ * Rotation: when total bytes across all recordings exceed maxTotalBytes
14
+ * (default 1 GB), the oldest file is removed.
15
+ */
16
+ export interface ReplayConfig {
17
+ /** Directory for recording files */
18
+ recordingsDir: string;
19
+ /** Maximum total bytes across all recordings before rotation (default 1 GB) */
20
+ maxTotalBytes: number;
21
+ }
22
+ export declare const DEFAULT_REPLAY_CONFIG: ReplayConfig;
23
+ export type JournalEventType = 'tool_call' | 'tool_result' | 'code_result';
24
+ export interface JournalEvent {
25
+ seq: number;
26
+ ts: number;
27
+ type: JournalEventType;
28
+ server?: string;
29
+ tool?: string;
30
+ args?: Record<string, unknown>;
31
+ result?: unknown;
32
+ }
33
+ export interface ReplayModification {
34
+ /** Zero-based sequence index to target */
35
+ at: number;
36
+ op: 'replace' | 'skip';
37
+ /** Replacement result value (only used when op === 'replace') */
38
+ with?: unknown;
39
+ }
40
+ export declare class ReplayRecorder {
41
+ private config;
42
+ private activeSessions;
43
+ constructor(config?: Partial<ReplayConfig>);
44
+ private ensureDir;
45
+ private rotate;
46
+ private appendEvent;
47
+ /** Start a new recording session. Returns the sessionId and recording path. */
48
+ startRecording(sessionId?: string): {
49
+ sessionId: string;
50
+ recordingPath: string;
51
+ };
52
+ /** Stop an active recording session. Returns the path and event count. */
53
+ stopRecording(sessionId: string): {
54
+ recordingPath: string;
55
+ eventCount: number;
56
+ };
57
+ /** Record a tool call event into an active session. */
58
+ recordToolCall(sessionId: string, server: string, tool: string, args: Record<string, unknown>): void;
59
+ /** Record a tool result event into an active session. */
60
+ recordToolResult(sessionId: string, server: string, tool: string, result: unknown): void;
61
+ /** Record the final code execution result. */
62
+ recordCodeResult(sessionId: string, result: unknown): void;
63
+ /** Return whether a session is currently active. */
64
+ isRecording(sessionId: string): boolean;
65
+ /**
66
+ * Load and parse a recording file. Returns the ordered events.
67
+ */
68
+ loadRecording(recordingPath: string): JournalEvent[];
69
+ /**
70
+ * Replay a recorded session.
71
+ *
72
+ * For each tool_call/tool_result pair in the journal the recorded result is
73
+ * returned unless a modification targets that sequence number:
74
+ * - op:'skip' → the tool call is omitted from the replayed sequence
75
+ * - op:'replace' → the recorded result is replaced with modification.with
76
+ *
77
+ * The final code_result is compared against the replayed sequence to detect
78
+ * divergence.
79
+ *
80
+ * This implementation operates fully in-memory against the journal — it does
81
+ * NOT re-execute Deno code (that would require a live executor). It reconstructs
82
+ * the recorded call sequence and applies modifications, returning what the
83
+ * sandbox would have seen.
84
+ */
85
+ replay(recordingPath: string, modifications?: ReplayModification[]): {
86
+ result: unknown;
87
+ events: JournalEvent[];
88
+ divergence?: {
89
+ at: number;
90
+ expected: unknown;
91
+ actual: unknown;
92
+ };
93
+ };
94
+ /** List all recording files sorted by modification time (newest first). */
95
+ listRecordings(): Array<{
96
+ sessionId: string;
97
+ path: string;
98
+ sizeBytes: number;
99
+ createdAt: number;
100
+ }>;
101
+ }
102
+ export declare function getReplayRecorder(config?: Partial<ReplayConfig>): ReplayRecorder;
103
+ export declare function shutdownReplayRecorder(): void;
104
+ //# sourceMappingURL=replay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.d.ts","sourceRoot":"","sources":["../../src/observability/replay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAiBH,MAAM,WAAW,YAAY;IAC3B,oCAAoC;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,qBAAqB,EAAE,YAGnC,CAAC;AAMF,MAAM,MAAM,gBAAgB,GAAG,WAAW,GAAG,aAAa,GAAG,aAAa,CAAC;AAE3E,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD,MAAM,WAAW,kBAAkB;IACjC,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,SAAS,GAAG,MAAM,CAAC;IACvB,iEAAiE;IACjE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA4CD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,cAAc,CAAyC;gBAEnD,MAAM,GAAE,OAAO,CAAC,YAAY,CAAM;IAI9C,OAAO,CAAC,SAAS;IAMjB,OAAO,CAAC,MAAM;IASd,OAAO,CAAC,WAAW;IAcnB,+EAA+E;IAC/E,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE;IAuBhF,0EAA0E;IAC1E,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE;IAa/E,uDAAuD;IACvD,cAAc,CACZ,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,IAAI;IAMP,yDAAyD;IACzD,gBAAgB,CACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,GACd,IAAI;IAMP,8CAA8C;IAC9C,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;IAM1D,oDAAoD;IACpD,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAQvC;;OAEG;IACH,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,YAAY,EAAE;IAUpD;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CACJ,aAAa,EAAE,MAAM,EACrB,aAAa,GAAE,kBAAkB,EAAO,GACvC;QACD,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,YAAY,EAAE,CAAC;QACvB,UAAU,CAAC,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,OAAO,CAAC;YAAC,MAAM,EAAE,OAAO,CAAA;SAAE,CAAC;KACjE;IA4CD,2EAA2E;IAC3E,cAAc,IAAI,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CAgBnG;AAMD,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,cAAc,CAKhF;AAED,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Replay Recorder
3
+ *
4
+ * Records execute_code sessions to JSONL journals under
5
+ * ~/.mcp-conductor/recordings/. Supports deterministic replay with optional
6
+ * per-event modifications (replace or skip). Detects divergence when the
7
+ * replayed result differs from the recorded result.
8
+ *
9
+ * Journal line format (one JSON object per line):
10
+ * { "seq": <number>, "ts": <epoch-ms>, "type": "tool_call"|"tool_result"|"code_result",
11
+ * "server": <string>, "tool": <string>, "args": <object>, "result": <unknown> }
12
+ *
13
+ * Rotation: when total bytes across all recordings exceed maxTotalBytes
14
+ * (default 1 GB), the oldest file is removed.
15
+ */
16
+ import { appendFileSync, existsSync, mkdirSync, readdirSync, statSync, unlinkSync, readFileSync, writeFileSync, } from 'node:fs';
17
+ import { homedir } from 'node:os';
18
+ import { join, basename } from 'node:path';
19
+ import { randomUUID } from 'node:crypto';
20
+ import { logger } from '../utils/index.js';
21
+ export const DEFAULT_REPLAY_CONFIG = {
22
+ recordingsDir: join(homedir(), '.mcp-conductor', 'recordings'),
23
+ maxTotalBytes: 1_073_741_824, // 1 GB
24
+ };
25
+ // ---------------------------------------------------------------------------
26
+ // Helper: directory total bytes
27
+ // ---------------------------------------------------------------------------
28
+ function dirTotalBytes(dir) {
29
+ if (!existsSync(dir))
30
+ return 0;
31
+ return readdirSync(dir)
32
+ .filter((f) => f.endsWith('.jsonl'))
33
+ .reduce((total, f) => {
34
+ try {
35
+ return total + statSync(join(dir, f)).size;
36
+ }
37
+ catch {
38
+ return total;
39
+ }
40
+ }, 0);
41
+ }
42
+ function oldestFile(dir) {
43
+ if (!existsSync(dir))
44
+ return null;
45
+ const files = readdirSync(dir)
46
+ .filter((f) => f.endsWith('.jsonl'))
47
+ .map((f) => ({ name: f, mtime: statSync(join(dir, f)).mtimeMs }))
48
+ .sort((a, b) => a.mtime - b.mtime);
49
+ const first = files[0];
50
+ return first ? join(dir, first.name) : null;
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // ReplayRecorder
54
+ // ---------------------------------------------------------------------------
55
+ export class ReplayRecorder {
56
+ config;
57
+ activeSessions = new Map();
58
+ constructor(config = {}) {
59
+ this.config = { ...DEFAULT_REPLAY_CONFIG, ...config };
60
+ }
61
+ ensureDir() {
62
+ if (!existsSync(this.config.recordingsDir)) {
63
+ mkdirSync(this.config.recordingsDir, { recursive: true });
64
+ }
65
+ }
66
+ rotate() {
67
+ while (dirTotalBytes(this.config.recordingsDir) > this.config.maxTotalBytes) {
68
+ const oldest = oldestFile(this.config.recordingsDir);
69
+ if (!oldest)
70
+ break;
71
+ logger.info('ReplayRecorder: rotating old recording', { file: basename(oldest) });
72
+ unlinkSync(oldest);
73
+ }
74
+ }
75
+ appendEvent(session, event) {
76
+ const fullEvent = {
77
+ seq: session.seq++,
78
+ ts: Date.now(),
79
+ ...event,
80
+ };
81
+ appendFileSync(session.recordingPath, JSON.stringify(fullEvent) + '\n', 'utf8');
82
+ session.eventCount++;
83
+ }
84
+ // ---------------------------------------------------------------------------
85
+ // Public API
86
+ // ---------------------------------------------------------------------------
87
+ /** Start a new recording session. Returns the sessionId and recording path. */
88
+ startRecording(sessionId) {
89
+ this.ensureDir();
90
+ this.rotate();
91
+ const id = sessionId ?? randomUUID();
92
+ const filename = `${id}.jsonl`;
93
+ const recordingPath = join(this.config.recordingsDir, filename);
94
+ // Create an empty file to claim the name
95
+ writeFileSync(recordingPath, '', 'utf8');
96
+ const session = {
97
+ sessionId: id,
98
+ recordingPath,
99
+ seq: 0,
100
+ eventCount: 0,
101
+ };
102
+ this.activeSessions.set(id, session);
103
+ logger.info('ReplayRecorder: started recording', { sessionId: id, recordingPath });
104
+ return { sessionId: id, recordingPath };
105
+ }
106
+ /** Stop an active recording session. Returns the path and event count. */
107
+ stopRecording(sessionId) {
108
+ const session = this.activeSessions.get(sessionId);
109
+ if (!session) {
110
+ throw new Error(`No active recording session: ${sessionId}`);
111
+ }
112
+ this.activeSessions.delete(sessionId);
113
+ logger.info('ReplayRecorder: stopped recording', {
114
+ sessionId,
115
+ eventCount: session.eventCount,
116
+ });
117
+ return { recordingPath: session.recordingPath, eventCount: session.eventCount };
118
+ }
119
+ /** Record a tool call event into an active session. */
120
+ recordToolCall(sessionId, server, tool, args) {
121
+ const session = this.activeSessions.get(sessionId);
122
+ if (!session)
123
+ return;
124
+ this.appendEvent(session, { type: 'tool_call', server, tool, args });
125
+ }
126
+ /** Record a tool result event into an active session. */
127
+ recordToolResult(sessionId, server, tool, result) {
128
+ const session = this.activeSessions.get(sessionId);
129
+ if (!session)
130
+ return;
131
+ this.appendEvent(session, { type: 'tool_result', server, tool, result });
132
+ }
133
+ /** Record the final code execution result. */
134
+ recordCodeResult(sessionId, result) {
135
+ const session = this.activeSessions.get(sessionId);
136
+ if (!session)
137
+ return;
138
+ this.appendEvent(session, { type: 'code_result', result });
139
+ }
140
+ /** Return whether a session is currently active. */
141
+ isRecording(sessionId) {
142
+ return this.activeSessions.has(sessionId);
143
+ }
144
+ // ---------------------------------------------------------------------------
145
+ // Replay
146
+ // ---------------------------------------------------------------------------
147
+ /**
148
+ * Load and parse a recording file. Returns the ordered events.
149
+ */
150
+ loadRecording(recordingPath) {
151
+ if (!existsSync(recordingPath)) {
152
+ throw new Error(`Recording not found: ${recordingPath}`);
153
+ }
154
+ const lines = readFileSync(recordingPath, 'utf8')
155
+ .split('\n')
156
+ .filter((l) => l.trim().length > 0);
157
+ return lines.map((l) => JSON.parse(l));
158
+ }
159
+ /**
160
+ * Replay a recorded session.
161
+ *
162
+ * For each tool_call/tool_result pair in the journal the recorded result is
163
+ * returned unless a modification targets that sequence number:
164
+ * - op:'skip' → the tool call is omitted from the replayed sequence
165
+ * - op:'replace' → the recorded result is replaced with modification.with
166
+ *
167
+ * The final code_result is compared against the replayed sequence to detect
168
+ * divergence.
169
+ *
170
+ * This implementation operates fully in-memory against the journal — it does
171
+ * NOT re-execute Deno code (that would require a live executor). It reconstructs
172
+ * the recorded call sequence and applies modifications, returning what the
173
+ * sandbox would have seen.
174
+ */
175
+ replay(recordingPath, modifications = []) {
176
+ const events = this.loadRecording(recordingPath);
177
+ const modMap = new Map(modifications.map((m) => [m.at, m]));
178
+ const replayed = [];
179
+ let replayedResult = undefined;
180
+ let divergence;
181
+ let replaySeq = 0;
182
+ for (const event of events) {
183
+ const mod = modMap.get(event.seq);
184
+ if (mod?.op === 'skip') {
185
+ // Skip this event — do not include in replayed sequence
186
+ logger.debug('ReplayRecorder: skipping event', { seq: event.seq });
187
+ continue;
188
+ }
189
+ if (event.type === 'code_result') {
190
+ // Compare recorded result with what we've accumulated
191
+ const expected = event.result;
192
+ // In no-modification replay the result is identical to recorded
193
+ const actual = mod?.op === 'replace' ? mod.with : event.result;
194
+ replayedResult = actual;
195
+ if (JSON.stringify(actual) !== JSON.stringify(expected)) {
196
+ divergence = { at: event.seq, expected, actual };
197
+ }
198
+ replayed.push({ ...event, seq: replaySeq++, result: actual });
199
+ continue;
200
+ }
201
+ if (mod?.op === 'replace' && event.type === 'tool_result') {
202
+ replayed.push({ ...event, seq: replaySeq++, result: mod.with });
203
+ continue;
204
+ }
205
+ replayed.push({ ...event, seq: replaySeq++ });
206
+ }
207
+ return { result: replayedResult, events: replayed, divergence };
208
+ }
209
+ /** List all recording files sorted by modification time (newest first). */
210
+ listRecordings() {
211
+ if (!existsSync(this.config.recordingsDir))
212
+ return [];
213
+ return readdirSync(this.config.recordingsDir)
214
+ .filter((f) => f.endsWith('.jsonl'))
215
+ .map((f) => {
216
+ const p = join(this.config.recordingsDir, f);
217
+ const stat = statSync(p);
218
+ return {
219
+ sessionId: f.replace('.jsonl', ''),
220
+ path: p,
221
+ sizeBytes: stat.size,
222
+ createdAt: stat.mtimeMs,
223
+ };
224
+ })
225
+ .sort((a, b) => b.createdAt - a.createdAt);
226
+ }
227
+ }
228
+ // Module-level singleton
229
+ let _instance = null;
230
+ export function getReplayRecorder(config) {
231
+ if (!_instance) {
232
+ _instance = new ReplayRecorder(config);
233
+ }
234
+ return _instance;
235
+ }
236
+ export function shutdownReplayRecorder() {
237
+ _instance = null;
238
+ }
239
+ //# sourceMappingURL=replay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay.js","sourceRoot":"","sources":["../../src/observability/replay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Built-in routing recommendations for well-known MCP servers.
3
+ *
4
+ * These defaults apply when a server is discovered but has no user-provided
5
+ * routing annotation. User config always takes precedence — these are applied
6
+ * only when `routing` is absent from a tool's existing registry entry.
7
+ *
8
+ * Rationale for each entry:
9
+ * - github: read-only identity/listing tools are safe direct passthrough;
10
+ * mutation tools stay execute_code to preserve sandbox audit trail.
11
+ * - filesystem: read-only traversal is passthrough; writes/deletes stay in
12
+ * execute_code so the sandbox can enforce path policies.
13
+ * - brave-search: single query → result, no side effects, tiny response.
14
+ *
15
+ * @module registry/built-in-recommendations
16
+ */
17
+ /**
18
+ * Per-server routing recommendations.
19
+ *
20
+ * Each entry maps a server name to:
21
+ * - `passthrough`: tools that should be exposed as first-class MCP tools.
22
+ *
23
+ * Every tool not listed in `passthrough` defaults to `execute_code`.
24
+ */
25
+ export interface ServerRoutingRecommendation {
26
+ /** Tool names that should be routed as passthrough. */
27
+ passthrough: string[];
28
+ }
29
+ /**
30
+ * Default routing table for known public MCP servers.
31
+ *
32
+ * Apply with `applyBuiltInRecommendations()` after `registry.refresh()`.
33
+ * User config overrides (any existing `routing` annotation) are preserved.
34
+ */
35
+ export declare const BUILT_IN_ROUTING: Record<string, ServerRoutingRecommendation>;
36
+ /**
37
+ * Apply built-in routing recommendations to registry-discovered tools.
38
+ *
39
+ * Only sets `routing` when none is already present — user annotations and
40
+ * config-file overrides are never overwritten.
41
+ *
42
+ * Returns the number of tools that were annotated.
43
+ *
44
+ * @param tools All tools returned by `registry.getAllTools()`.
45
+ * @param annotate The `registry.annotate()` method bound to the ToolRegistry.
46
+ */
47
+ export declare function applyBuiltInRecommendations(tools: Array<{
48
+ server: string;
49
+ name: string;
50
+ routing?: string;
51
+ }>, annotate: (server: string, name: string, meta: {
52
+ routing: 'passthrough' | 'execute_code';
53
+ }) => void): number;
54
+ //# sourceMappingURL=built-in-recommendations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in-recommendations.d.ts","sourceRoot":"","sources":["../../src/registry/built-in-recommendations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C,uDAAuD;IACvD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAUxE,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EAChE,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,OAAO,EAAE,aAAa,GAAG,cAAc,CAAA;CAAE,KAAK,IAAI,GAClG,MAAM,CAwBR"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Built-in routing recommendations for well-known MCP servers.
3
+ *
4
+ * These defaults apply when a server is discovered but has no user-provided
5
+ * routing annotation. User config always takes precedence — these are applied
6
+ * only when `routing` is absent from a tool's existing registry entry.
7
+ *
8
+ * Rationale for each entry:
9
+ * - github: read-only identity/listing tools are safe direct passthrough;
10
+ * mutation tools stay execute_code to preserve sandbox audit trail.
11
+ * - filesystem: read-only traversal is passthrough; writes/deletes stay in
12
+ * execute_code so the sandbox can enforce path policies.
13
+ * - brave-search: single query → result, no side effects, tiny response.
14
+ *
15
+ * @module registry/built-in-recommendations
16
+ */
17
+ /**
18
+ * Default routing table for known public MCP servers.
19
+ *
20
+ * Apply with `applyBuiltInRecommendations()` after `registry.refresh()`.
21
+ * User config overrides (any existing `routing` annotation) are preserved.
22
+ */
23
+ export const BUILT_IN_ROUTING = {
24
+ github: {
25
+ passthrough: ['get_me', 'list_repositories'],
26
+ },
27
+ filesystem: {
28
+ passthrough: ['read_file', 'list_directory'],
29
+ },
30
+ 'brave-search': {
31
+ passthrough: ['brave_web_search'],
32
+ },
33
+ };
34
+ /**
35
+ * Apply built-in routing recommendations to registry-discovered tools.
36
+ *
37
+ * Only sets `routing` when none is already present — user annotations and
38
+ * config-file overrides are never overwritten.
39
+ *
40
+ * Returns the number of tools that were annotated.
41
+ *
42
+ * @param tools All tools returned by `registry.getAllTools()`.
43
+ * @param annotate The `registry.annotate()` method bound to the ToolRegistry.
44
+ */
45
+ export function applyBuiltInRecommendations(tools, annotate) {
46
+ let annotated = 0;
47
+ for (const tool of tools) {
48
+ // Never override a user-configured routing value.
49
+ if (tool.routing !== undefined) {
50
+ continue;
51
+ }
52
+ const rec = BUILT_IN_ROUTING[tool.server];
53
+ if (!rec) {
54
+ // Unknown server — default remains execute_code (no annotation needed).
55
+ continue;
56
+ }
57
+ const routing = rec.passthrough.includes(tool.name)
58
+ ? 'passthrough'
59
+ : 'execute_code';
60
+ annotate(tool.server, tool.name, { routing });
61
+ annotated++;
62
+ }
63
+ return annotated;
64
+ }
65
+ //# sourceMappingURL=built-in-recommendations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in-recommendations.js","sourceRoot":"","sources":["../../src/registry/built-in-recommendations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAeH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAgD;IAC3E,MAAM,EAAE;QACN,WAAW,EAAE,CAAC,QAAQ,EAAE,mBAAmB,CAAC;KAC7C;IACD,UAAU,EAAE;QACV,WAAW,EAAE,CAAC,WAAW,EAAE,gBAAgB,CAAC;KAC7C;IACD,cAAc,EAAE;QACd,WAAW,EAAE,CAAC,kBAAkB,CAAC;KAClC;CACF,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAAgE,EAChE,QAAmG;IAEnG,IAAI,SAAS,GAAG,CAAC,CAAC;IAElB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,kDAAkD;QAClD,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,wEAAwE;YACxE,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAmC,GAAG,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;YACjF,CAAC,CAAC,aAAa;YACf,CAAC,CAAC,cAAc,CAAC;QAEnB,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;QAC9C,SAAS,EAAE,CAAC;IACd,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Registry events — change notifications emitted when the tool catalog
3
+ * is mutated by a refresh, hot-reload, or annotation update.
4
+ * @module registry/events
5
+ */
6
+ import { EventEmitter } from 'node:events';
7
+ import type { ToolDefinition } from './index.js';
8
+ export type RegistryEventType = 'tool-added' | 'tool-removed' | 'tool-updated' | 'server-connected' | 'server-disconnected';
9
+ export interface RegistryEvent {
10
+ type: RegistryEventType;
11
+ server: string;
12
+ tool?: string;
13
+ before?: ToolDefinition;
14
+ after?: ToolDefinition;
15
+ at: number;
16
+ }
17
+ /**
18
+ * Typed event emitter for registry changes.
19
+ * Callers subscribe via `ToolRegistry.watch()` rather than using this directly.
20
+ */
21
+ export declare class RegistryEmitter extends EventEmitter {
22
+ emit(event: 'change', registryEvent: RegistryEvent): boolean;
23
+ on(event: 'change', listener: (registryEvent: RegistryEvent) => void): this;
24
+ off(event: 'change', listener: (registryEvent: RegistryEvent) => void): this;
25
+ }
26
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/registry/events.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,iBAAiB,GACzB,YAAY,GACZ,cAAc,GACd,cAAc,GACd,kBAAkB,GAClB,qBAAqB,CAAC;AAE1B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,aAAa,GAAG,OAAO;IAI5D,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IAI3E,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;CAG7E"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Registry events — change notifications emitted when the tool catalog
3
+ * is mutated by a refresh, hot-reload, or annotation update.
4
+ * @module registry/events
5
+ */
6
+ import { EventEmitter } from 'node:events';
7
+ /**
8
+ * Typed event emitter for registry changes.
9
+ * Callers subscribe via `ToolRegistry.watch()` rather than using this directly.
10
+ */
11
+ export class RegistryEmitter extends EventEmitter {
12
+ emit(event, registryEvent) {
13
+ return super.emit('change', registryEvent);
14
+ }
15
+ on(event, listener) {
16
+ return super.on('change', listener);
17
+ }
18
+ off(event, listener) {
19
+ return super.off('change', listener);
20
+ }
21
+ }
22
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/registry/events.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAmB3C;;;GAGG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;IAC/C,IAAI,CAAC,KAAe,EAAE,aAA4B;QAChD,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC7C,CAAC;IAED,EAAE,CAAC,KAAe,EAAE,QAAgD;QAClE,OAAO,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,GAAG,CAAC,KAAe,EAAE,QAAgD;QACnE,OAAO,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACvC,CAAC;CACF"}