@darkiceinteractive/mcp-conductor 1.1.0 → 3.0.0-beta.1

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 (293) 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 +65 -1
  7. package/dist/bridge/http-server.d.ts.map +1 -1
  8. package/dist/bridge/http-server.js +192 -7
  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/bridge/session-registry.d.ts +64 -0
  19. package/dist/bridge/session-registry.d.ts.map +1 -0
  20. package/dist/bridge/session-registry.js +124 -0
  21. package/dist/bridge/session-registry.js.map +1 -0
  22. package/dist/cache/cache.d.ts +43 -0
  23. package/dist/cache/cache.d.ts.map +1 -0
  24. package/dist/cache/cache.js +167 -0
  25. package/dist/cache/cache.js.map +1 -0
  26. package/dist/cache/delta.d.ts +32 -0
  27. package/dist/cache/delta.d.ts.map +1 -0
  28. package/dist/cache/delta.js +131 -0
  29. package/dist/cache/delta.js.map +1 -0
  30. package/dist/cache/disk.d.ts +65 -0
  31. package/dist/cache/disk.d.ts.map +1 -0
  32. package/dist/cache/disk.js +238 -0
  33. package/dist/cache/disk.js.map +1 -0
  34. package/dist/cache/index.d.ts +53 -0
  35. package/dist/cache/index.d.ts.map +1 -0
  36. package/dist/cache/index.js +12 -0
  37. package/dist/cache/index.js.map +1 -0
  38. package/dist/cache/key.d.ts +44 -0
  39. package/dist/cache/key.d.ts.map +1 -0
  40. package/dist/cache/key.js +83 -0
  41. package/dist/cache/key.js.map +1 -0
  42. package/dist/cache/lru.d.ts +57 -0
  43. package/dist/cache/lru.d.ts.map +1 -0
  44. package/dist/cache/lru.js +112 -0
  45. package/dist/cache/lru.js.map +1 -0
  46. package/dist/cache/policy.d.ts +34 -0
  47. package/dist/cache/policy.d.ts.map +1 -0
  48. package/dist/cache/policy.js +95 -0
  49. package/dist/cache/policy.js.map +1 -0
  50. package/dist/cli/commands/doctor.d.ts +33 -0
  51. package/dist/cli/commands/doctor.d.ts.map +1 -0
  52. package/dist/cli/commands/doctor.js +135 -0
  53. package/dist/cli/commands/doctor.js.map +1 -0
  54. package/dist/cli/commands/export-servers.d.ts +22 -0
  55. package/dist/cli/commands/export-servers.d.ts.map +1 -0
  56. package/dist/cli/commands/export-servers.js +45 -0
  57. package/dist/cli/commands/export-servers.js.map +1 -0
  58. package/dist/cli/commands/import-servers.d.ts +57 -0
  59. package/dist/cli/commands/import-servers.d.ts.map +1 -0
  60. package/dist/cli/commands/import-servers.js +137 -0
  61. package/dist/cli/commands/import-servers.js.map +1 -0
  62. package/dist/cli/commands/routing.d.ts +34 -0
  63. package/dist/cli/commands/routing.d.ts.map +1 -0
  64. package/dist/cli/commands/routing.js +60 -0
  65. package/dist/cli/commands/routing.js.map +1 -0
  66. package/dist/cli/commands/test-server.d.ts +34 -0
  67. package/dist/cli/commands/test-server.d.ts.map +1 -0
  68. package/dist/cli/commands/test-server.js +86 -0
  69. package/dist/cli/commands/test-server.js.map +1 -0
  70. package/dist/cli/daemon.d.ts +60 -0
  71. package/dist/cli/daemon.d.ts.map +1 -0
  72. package/dist/cli/daemon.js +244 -0
  73. package/dist/cli/daemon.js.map +1 -0
  74. package/dist/cli/replay.d.ts +16 -0
  75. package/dist/cli/replay.d.ts.map +1 -0
  76. package/dist/cli/replay.js +89 -0
  77. package/dist/cli/replay.js.map +1 -0
  78. package/dist/cli/wizard/setup.d.ts +12 -0
  79. package/dist/cli/wizard/setup.d.ts.map +1 -0
  80. package/dist/cli/wizard/setup.js +71 -0
  81. package/dist/cli/wizard/setup.js.map +1 -0
  82. package/dist/config/defaults.d.ts +10 -0
  83. package/dist/config/defaults.d.ts.map +1 -1
  84. package/dist/config/defaults.js +14 -1
  85. package/dist/config/defaults.js.map +1 -1
  86. package/dist/config/schema.d.ts +34 -0
  87. package/dist/config/schema.d.ts.map +1 -1
  88. package/dist/daemon/client.d.ts +97 -0
  89. package/dist/daemon/client.d.ts.map +1 -0
  90. package/dist/daemon/client.js +279 -0
  91. package/dist/daemon/client.js.map +1 -0
  92. package/dist/daemon/discovery.d.ts +50 -0
  93. package/dist/daemon/discovery.d.ts.map +1 -0
  94. package/dist/daemon/discovery.js +104 -0
  95. package/dist/daemon/discovery.js.map +1 -0
  96. package/dist/daemon/index.d.ts +16 -0
  97. package/dist/daemon/index.d.ts.map +1 -0
  98. package/dist/daemon/index.js +11 -0
  99. package/dist/daemon/index.js.map +1 -0
  100. package/dist/daemon/sandbox-api.d.ts +45 -0
  101. package/dist/daemon/sandbox-api.d.ts.map +1 -0
  102. package/dist/daemon/sandbox-api.js +74 -0
  103. package/dist/daemon/sandbox-api.js.map +1 -0
  104. package/dist/daemon/server.d.ts +65 -0
  105. package/dist/daemon/server.d.ts.map +1 -0
  106. package/dist/daemon/server.js +351 -0
  107. package/dist/daemon/server.js.map +1 -0
  108. package/dist/daemon/shared-kv.d.ts +81 -0
  109. package/dist/daemon/shared-kv.d.ts.map +1 -0
  110. package/dist/daemon/shared-kv.js +215 -0
  111. package/dist/daemon/shared-kv.js.map +1 -0
  112. package/dist/daemon/shared-lock.d.ts +71 -0
  113. package/dist/daemon/shared-lock.d.ts.map +1 -0
  114. package/dist/daemon/shared-lock.js +119 -0
  115. package/dist/daemon/shared-lock.js.map +1 -0
  116. package/dist/hub/mcp-hub.d.ts +23 -0
  117. package/dist/hub/mcp-hub.d.ts.map +1 -1
  118. package/dist/hub/mcp-hub.js +34 -1
  119. package/dist/hub/mcp-hub.js.map +1 -1
  120. package/dist/index.js +19 -0
  121. package/dist/index.js.map +1 -1
  122. package/dist/observability/anomaly.d.ts +67 -0
  123. package/dist/observability/anomaly.d.ts.map +1 -0
  124. package/dist/observability/anomaly.js +141 -0
  125. package/dist/observability/anomaly.js.map +1 -0
  126. package/dist/observability/cost-predictor.d.ts +49 -0
  127. package/dist/observability/cost-predictor.d.ts.map +1 -0
  128. package/dist/observability/cost-predictor.js +145 -0
  129. package/dist/observability/cost-predictor.js.map +1 -0
  130. package/dist/observability/hot-path.d.ts +49 -0
  131. package/dist/observability/hot-path.d.ts.map +1 -0
  132. package/dist/observability/hot-path.js +125 -0
  133. package/dist/observability/hot-path.js.map +1 -0
  134. package/dist/observability/index.d.ts +10 -0
  135. package/dist/observability/index.d.ts.map +1 -0
  136. package/dist/observability/index.js +10 -0
  137. package/dist/observability/index.js.map +1 -0
  138. package/dist/observability/replay.d.ts +104 -0
  139. package/dist/observability/replay.d.ts.map +1 -0
  140. package/dist/observability/replay.js +239 -0
  141. package/dist/observability/replay.js.map +1 -0
  142. package/dist/registry/built-in-recommendations.d.ts +54 -0
  143. package/dist/registry/built-in-recommendations.d.ts.map +1 -0
  144. package/dist/registry/built-in-recommendations.js +65 -0
  145. package/dist/registry/built-in-recommendations.js.map +1 -0
  146. package/dist/registry/events.d.ts +26 -0
  147. package/dist/registry/events.d.ts.map +1 -0
  148. package/dist/registry/events.js +22 -0
  149. package/dist/registry/events.js.map +1 -0
  150. package/dist/registry/index.d.ts +159 -0
  151. package/dist/registry/index.d.ts.map +1 -0
  152. package/dist/registry/index.js +12 -0
  153. package/dist/registry/index.js.map +1 -0
  154. package/dist/registry/registry.d.ts +87 -0
  155. package/dist/registry/registry.d.ts.map +1 -0
  156. package/dist/registry/registry.js +294 -0
  157. package/dist/registry/registry.js.map +1 -0
  158. package/dist/registry/snapshot.d.ts +42 -0
  159. package/dist/registry/snapshot.d.ts.map +1 -0
  160. package/dist/registry/snapshot.js +71 -0
  161. package/dist/registry/snapshot.js.map +1 -0
  162. package/dist/registry/typegen.d.ts +48 -0
  163. package/dist/registry/typegen.d.ts.map +1 -0
  164. package/dist/registry/typegen.js +200 -0
  165. package/dist/registry/typegen.js.map +1 -0
  166. package/dist/registry/validator.d.ts +23 -0
  167. package/dist/registry/validator.d.ts.map +1 -0
  168. package/dist/registry/validator.js +50 -0
  169. package/dist/registry/validator.js.map +1 -0
  170. package/dist/reliability/breaker.d.ts +57 -0
  171. package/dist/reliability/breaker.d.ts.map +1 -0
  172. package/dist/reliability/breaker.js +130 -0
  173. package/dist/reliability/breaker.js.map +1 -0
  174. package/dist/reliability/errors.d.ts +78 -0
  175. package/dist/reliability/errors.d.ts.map +1 -0
  176. package/dist/reliability/errors.js +160 -0
  177. package/dist/reliability/errors.js.map +1 -0
  178. package/dist/reliability/gateway.d.ts +88 -0
  179. package/dist/reliability/gateway.d.ts.map +1 -0
  180. package/dist/reliability/gateway.js +180 -0
  181. package/dist/reliability/gateway.js.map +1 -0
  182. package/dist/reliability/index.d.ts +20 -0
  183. package/dist/reliability/index.d.ts.map +1 -0
  184. package/dist/reliability/index.js +16 -0
  185. package/dist/reliability/index.js.map +1 -0
  186. package/dist/reliability/profile.d.ts +49 -0
  187. package/dist/reliability/profile.d.ts.map +1 -0
  188. package/dist/reliability/profile.js +58 -0
  189. package/dist/reliability/profile.js.map +1 -0
  190. package/dist/reliability/retry.d.ts +39 -0
  191. package/dist/reliability/retry.d.ts.map +1 -0
  192. package/dist/reliability/retry.js +51 -0
  193. package/dist/reliability/retry.js.map +1 -0
  194. package/dist/reliability/timeout.d.ts +34 -0
  195. package/dist/reliability/timeout.d.ts.map +1 -0
  196. package/dist/reliability/timeout.js +53 -0
  197. package/dist/reliability/timeout.js.map +1 -0
  198. package/dist/runtime/executor.d.ts +12 -0
  199. package/dist/runtime/executor.d.ts.map +1 -1
  200. package/dist/runtime/executor.js +148 -16
  201. package/dist/runtime/executor.js.map +1 -1
  202. package/dist/runtime/findtool/embed.d.ts +28 -0
  203. package/dist/runtime/findtool/embed.d.ts.map +1 -0
  204. package/dist/runtime/findtool/embed.js +85 -0
  205. package/dist/runtime/findtool/embed.js.map +1 -0
  206. package/dist/runtime/findtool/index.d.ts +52 -0
  207. package/dist/runtime/findtool/index.d.ts.map +1 -0
  208. package/dist/runtime/findtool/index.js +78 -0
  209. package/dist/runtime/findtool/index.js.map +1 -0
  210. package/dist/runtime/findtool/vector-index.d.ts +53 -0
  211. package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
  212. package/dist/runtime/findtool/vector-index.js +71 -0
  213. package/dist/runtime/findtool/vector-index.js.map +1 -0
  214. package/dist/runtime/helpers/budget.d.ts +27 -0
  215. package/dist/runtime/helpers/budget.d.ts.map +1 -0
  216. package/dist/runtime/helpers/budget.js +103 -0
  217. package/dist/runtime/helpers/budget.js.map +1 -0
  218. package/dist/runtime/helpers/compact.d.ts +32 -0
  219. package/dist/runtime/helpers/compact.d.ts.map +1 -0
  220. package/dist/runtime/helpers/compact.js +93 -0
  221. package/dist/runtime/helpers/compact.js.map +1 -0
  222. package/dist/runtime/helpers/delta.d.ts +45 -0
  223. package/dist/runtime/helpers/delta.d.ts.map +1 -0
  224. package/dist/runtime/helpers/delta.js +116 -0
  225. package/dist/runtime/helpers/delta.js.map +1 -0
  226. package/dist/runtime/helpers/index.d.ts +16 -0
  227. package/dist/runtime/helpers/index.d.ts.map +1 -0
  228. package/dist/runtime/helpers/index.js +13 -0
  229. package/dist/runtime/helpers/index.js.map +1 -0
  230. package/dist/runtime/helpers/summarize.d.ts +24 -0
  231. package/dist/runtime/helpers/summarize.d.ts.map +1 -0
  232. package/dist/runtime/helpers/summarize.js +124 -0
  233. package/dist/runtime/helpers/summarize.js.map +1 -0
  234. package/dist/runtime/helpers/worker-preload.d.ts +25 -0
  235. package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
  236. package/dist/runtime/helpers/worker-preload.js +223 -0
  237. package/dist/runtime/helpers/worker-preload.js.map +1 -0
  238. package/dist/runtime/index.d.ts +1 -0
  239. package/dist/runtime/index.d.ts.map +1 -1
  240. package/dist/runtime/index.js +1 -0
  241. package/dist/runtime/index.js.map +1 -1
  242. package/dist/runtime/pool/index.d.ts +11 -0
  243. package/dist/runtime/pool/index.d.ts.map +1 -0
  244. package/dist/runtime/pool/index.js +8 -0
  245. package/dist/runtime/pool/index.js.map +1 -0
  246. package/dist/runtime/pool/recycle.d.ts +44 -0
  247. package/dist/runtime/pool/recycle.d.ts.map +1 -0
  248. package/dist/runtime/pool/recycle.js +50 -0
  249. package/dist/runtime/pool/recycle.js.map +1 -0
  250. package/dist/runtime/pool/worker-pool.d.ts +77 -0
  251. package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
  252. package/dist/runtime/pool/worker-pool.js +216 -0
  253. package/dist/runtime/pool/worker-pool.js.map +1 -0
  254. package/dist/runtime/pool/worker.d.ts +80 -0
  255. package/dist/runtime/pool/worker.d.ts.map +1 -0
  256. package/dist/runtime/pool/worker.js +324 -0
  257. package/dist/runtime/pool/worker.js.map +1 -0
  258. package/dist/server/mcp-server.d.ts +6 -0
  259. package/dist/server/mcp-server.d.ts.map +1 -1
  260. package/dist/server/mcp-server.js +610 -45
  261. package/dist/server/mcp-server.js.map +1 -1
  262. package/dist/server/passthrough-registrar.d.ts +73 -0
  263. package/dist/server/passthrough-registrar.d.ts.map +1 -0
  264. package/dist/server/passthrough-registrar.js +110 -0
  265. package/dist/server/passthrough-registrar.js.map +1 -0
  266. package/dist/skills/skills-engine.d.ts +9 -1
  267. package/dist/skills/skills-engine.d.ts.map +1 -1
  268. package/dist/skills/skills-engine.js +20 -3
  269. package/dist/skills/skills-engine.js.map +1 -1
  270. package/dist/utils/index.d.ts +3 -0
  271. package/dist/utils/index.d.ts.map +1 -1
  272. package/dist/utils/index.js +3 -0
  273. package/dist/utils/index.js.map +1 -1
  274. package/dist/utils/logger.d.ts.map +1 -1
  275. package/dist/utils/logger.js +5 -1
  276. package/dist/utils/logger.js.map +1 -1
  277. package/dist/utils/orphan-watch.d.ts +34 -0
  278. package/dist/utils/orphan-watch.d.ts.map +1 -0
  279. package/dist/utils/orphan-watch.js +54 -0
  280. package/dist/utils/orphan-watch.js.map +1 -0
  281. package/dist/utils/redact.d.ts +15 -0
  282. package/dist/utils/redact.d.ts.map +1 -0
  283. package/dist/utils/redact.js +48 -0
  284. package/dist/utils/redact.js.map +1 -0
  285. package/dist/utils/tokenize.d.ts +55 -0
  286. package/dist/utils/tokenize.d.ts.map +1 -0
  287. package/dist/utils/tokenize.js +205 -0
  288. package/dist/utils/tokenize.js.map +1 -0
  289. package/dist/version.d.ts +3 -3
  290. package/dist/version.d.ts.map +1 -1
  291. package/dist/version.js +3 -3
  292. package/dist/version.js.map +1 -1
  293. package/package.json +13 -3
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Warm Deno Worker Pool
3
+ *
4
+ * Maintains a fixed pool of pre-warmed Deno workers so that the first
5
+ * execute_code call after startup hits an already-running sandbox.
6
+ *
7
+ * Lifecycle:
8
+ * 1. `new WorkerPool(opts)` — configure
9
+ * 2. `await pool.warmUp()` — spawn `size` workers concurrently
10
+ * 3. `await pool.execute(job)` — pick idle worker, run, release
11
+ * 4. `await pool.shutdown()` — drain in-flight jobs, terminate all workers
12
+ *
13
+ * Recycle policy (see recycle.ts):
14
+ * - After `maxJobsPerWorker` jobs the worker is replaced before termination
15
+ * - After `maxAgeMs` age the worker is replaced after its current job finishes
16
+ * - After any uncaught error the worker is replaced immediately
17
+ *
18
+ * Phase 5 plug-in: pass `preloadHelpers` to `WorkerPoolOptions` and the
19
+ * bootstrap script inside `worker.ts` will `await import()` each path before
20
+ * entering the job loop.
21
+ *
22
+ * @module runtime/pool/worker-pool
23
+ */
24
+ import { logger } from '../../utils/index.js';
25
+ import { PooledWorker } from './worker.js';
26
+ import { evaluateRecycle } from './recycle.js';
27
+ // ─────────────────────────────────────────────────────────────────────────────
28
+ // WorkerPool
29
+ // ─────────────────────────────────────────────────────────────────────────────
30
+ const DEFAULT_SIZE = 4;
31
+ const DEFAULT_MAX_JOBS = 100;
32
+ const DEFAULT_MAX_AGE_MS = 600_000;
33
+ const DEFAULT_ACQUIRE_TIMEOUT_MS = 5_000;
34
+ export class WorkerPool {
35
+ opts;
36
+ workers = [];
37
+ queue = [];
38
+ isShuttingDown = false;
39
+ isWarmedUp = false;
40
+ constructor(options) {
41
+ this.opts = {
42
+ size: options.size ?? DEFAULT_SIZE,
43
+ maxJobsPerWorker: options.maxJobsPerWorker ?? DEFAULT_MAX_JOBS,
44
+ maxAgeMs: options.maxAgeMs ?? DEFAULT_MAX_AGE_MS,
45
+ preloadTypesDir: options.preloadTypesDir,
46
+ preloadHelpers: options.preloadHelpers ?? [],
47
+ maxMemoryMb: options.maxMemoryMb ?? 128,
48
+ bridgeUrl: options.bridgeUrl ?? 'http://127.0.0.1:9847',
49
+ };
50
+ }
51
+ /** Pre-spawn all workers. Must be called before `execute()`. */
52
+ async warmUp() {
53
+ if (this.isWarmedUp)
54
+ return;
55
+ const workerOpts = {
56
+ preloadTypesDir: this.opts.preloadTypesDir,
57
+ preloadHelpers: this.opts.preloadHelpers,
58
+ maxMemoryMb: this.opts.maxMemoryMb,
59
+ bridgeUrl: this.opts.bridgeUrl,
60
+ };
61
+ const spawns = Array.from({ length: this.opts.size }, async () => {
62
+ const w = new PooledWorker(workerOpts);
63
+ await w.start();
64
+ this.workers.push(w);
65
+ });
66
+ await Promise.allSettled(spawns);
67
+ const alive = this.workers.filter((w) => w.currentState !== 'dead').length;
68
+ logger.info('WorkerPool warmed up', { requested: this.opts.size, alive });
69
+ this.isWarmedUp = true;
70
+ }
71
+ /**
72
+ * Execute a job on an idle worker.
73
+ *
74
+ * If no idle worker is available, the job is queued until one becomes
75
+ * free or the acquire timeout elapses.
76
+ */
77
+ async execute(job, execOpts = {}) {
78
+ if (this.isShuttingDown) {
79
+ throw new Error('WorkerPool is shutting down');
80
+ }
81
+ const fullJob = {
82
+ ...job,
83
+ signal: execOpts.signal,
84
+ };
85
+ const worker = this._findIdle();
86
+ if (worker) {
87
+ return this._runOnWorker(worker, fullJob);
88
+ }
89
+ // Queue the job
90
+ const acquireTimeoutMs = execOpts.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS;
91
+ return new Promise((resolve, reject) => {
92
+ const timeoutTimer = setTimeout(() => {
93
+ const idx = this.queue.findIndex((q) => q.job.id === fullJob.id);
94
+ if (idx !== -1)
95
+ this.queue.splice(idx, 1);
96
+ reject(new Error(`WorkerPool: acquire timeout after ${acquireTimeoutMs}ms`));
97
+ }, acquireTimeoutMs);
98
+ if (timeoutTimer.unref)
99
+ timeoutTimer.unref();
100
+ this.queue.push({
101
+ job: fullJob,
102
+ resolve: resolve,
103
+ reject,
104
+ timeoutTimer,
105
+ });
106
+ });
107
+ }
108
+ size() {
109
+ return this.workers.filter((w) => w.currentState !== 'dead').length;
110
+ }
111
+ busyCount() {
112
+ return this.workers.filter((w) => w.currentState === 'busy').length;
113
+ }
114
+ idleCount() {
115
+ return this.workers.filter((w) => w.currentState === 'idle').length;
116
+ }
117
+ /** Gracefully drain all in-flight jobs then terminate all workers. */
118
+ async shutdown() {
119
+ this.isShuttingDown = true;
120
+ // Reject queued jobs that haven't started
121
+ for (const queued of this.queue) {
122
+ clearTimeout(queued.timeoutTimer);
123
+ queued.reject(new Error('WorkerPool shut down'));
124
+ }
125
+ this.queue.length = 0;
126
+ // Drain busy workers (wait for current jobs to finish, then terminate)
127
+ await Promise.allSettled(this.workers.map((w) => w.shutdown(true)));
128
+ this.workers.length = 0;
129
+ logger.info('WorkerPool: shutdown complete');
130
+ }
131
+ // ─────────────────────────────────────────────────────────────────────────
132
+ // Private
133
+ // ─────────────────────────────────────────────────────────────────────────
134
+ _findIdle() {
135
+ return this.workers.find((w) => w.isIdle && w.currentState === 'idle');
136
+ }
137
+ async _runOnWorker(worker, job) {
138
+ let result;
139
+ try {
140
+ result = await worker.execute(job);
141
+ }
142
+ catch (err) {
143
+ // Worker errored — mark for recycle and propagate
144
+ await this._maybeRecycle(worker);
145
+ throw err;
146
+ }
147
+ // Post-job recycle check (age / job-count triggers)
148
+ await this._maybeRecycle(worker);
149
+ // Drain one queued job onto the (now idle) worker or next available idle
150
+ this._drainQueue();
151
+ if (!result.success && result.error) {
152
+ throw new Error(result.error.message);
153
+ }
154
+ return result.result;
155
+ }
156
+ async _maybeRecycle(worker) {
157
+ const decision = evaluateRecycle({
158
+ id: worker.id,
159
+ state: worker.currentState,
160
+ createdAt: worker.createdAt,
161
+ jobsRun: worker.jobsRun,
162
+ }, { maxJobsPerWorker: this.opts.maxJobsPerWorker, maxAgeMs: this.opts.maxAgeMs });
163
+ if (!decision.shouldRecycle)
164
+ return;
165
+ logger.debug('WorkerPool: recycling worker', { workerId: worker.id, reason: decision.reason });
166
+ // Spawn replacement first to maintain capacity
167
+ const workerOpts = {
168
+ preloadTypesDir: this.opts.preloadTypesDir,
169
+ preloadHelpers: this.opts.preloadHelpers,
170
+ maxMemoryMb: this.opts.maxMemoryMb,
171
+ bridgeUrl: this.opts.bridgeUrl,
172
+ };
173
+ if (!this.isShuttingDown) {
174
+ const replacement = new PooledWorker(workerOpts);
175
+ // Start async — don't block the caller
176
+ replacement.start().then(() => {
177
+ const idx = this.workers.indexOf(worker);
178
+ if (idx !== -1) {
179
+ this.workers.splice(idx, 1, replacement);
180
+ }
181
+ else {
182
+ this.workers.push(replacement);
183
+ }
184
+ this._drainQueue();
185
+ logger.debug('WorkerPool: replacement worker ready', { workerId: replacement.id });
186
+ }).catch((err) => {
187
+ logger.error('WorkerPool: replacement spawn failed', { err: String(err) });
188
+ // Remove old dead worker anyway
189
+ this._removeWorker(worker);
190
+ });
191
+ }
192
+ // Terminate old worker (drainFirst=false: it's already idle or dead)
193
+ await worker.shutdown(false);
194
+ if (this.isShuttingDown) {
195
+ this._removeWorker(worker);
196
+ }
197
+ }
198
+ _removeWorker(worker) {
199
+ const idx = this.workers.indexOf(worker);
200
+ if (idx !== -1)
201
+ this.workers.splice(idx, 1);
202
+ }
203
+ _drainQueue() {
204
+ while (this.queue.length > 0) {
205
+ const idle = this._findIdle();
206
+ if (!idle)
207
+ break;
208
+ const queued = this.queue.shift();
209
+ clearTimeout(queued.timeoutTimer);
210
+ this._runOnWorker(idle, queued.job)
211
+ .then((result) => queued.resolve(result))
212
+ .catch((err) => queued.reject(err));
213
+ }
214
+ }
215
+ }
216
+ //# sourceMappingURL=worker-pool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-pool.js","sourceRoot":"","sources":["../../../src/runtime/pool/worker-pool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Individual Deno Worker Lifecycle
3
+ *
4
+ * Manages a single warm Deno worker subprocess. The worker runs a persistent
5
+ * bootstrap script that:
6
+ * 1. Accepts a list of preload helper scripts (Phase 5 plug-in point)
7
+ * 2. Waits for job messages on stdin, executes the code, returns results on stdout
8
+ *
9
+ * Communication protocol (newline-delimited JSON over stdio):
10
+ * host → worker: { id, code, context }
11
+ * worker → host: { id, success, result?, error?, logs }
12
+ *
13
+ * @module runtime/pool/worker
14
+ */
15
+ export interface WorkerOptions {
16
+ /** Directory containing generated .d.ts files from the registry */
17
+ preloadTypesDir: string;
18
+ /**
19
+ * Additional helper scripts to preload (absolute paths or Deno URLs).
20
+ * Phase 5 (Agent E) plugs compact/summarize/delta helpers in here.
21
+ */
22
+ preloadHelpers?: string[];
23
+ /** Maximum old-space memory for the Deno process (MB) */
24
+ maxMemoryMb?: number;
25
+ /** Bridge URL the sandbox code uses for MCP calls */
26
+ bridgeUrl?: string;
27
+ }
28
+ export interface WorkerJob {
29
+ /** Unique job identifier for routing responses */
30
+ id: string;
31
+ /** TypeScript source code to execute */
32
+ code: string;
33
+ /** Execution context injected as global variables */
34
+ context: Record<string, unknown>;
35
+ /** Optional AbortSignal to cancel in-flight job */
36
+ signal?: AbortSignal;
37
+ }
38
+ export interface WorkerResult {
39
+ id: string;
40
+ success: boolean;
41
+ result?: unknown;
42
+ error?: {
43
+ message: string;
44
+ stack?: string;
45
+ };
46
+ logs: string[];
47
+ }
48
+ export type WorkerState = 'idle' | 'busy' | 'recycling' | 'dead';
49
+ export declare class PooledWorker {
50
+ private readonly opts;
51
+ readonly id: string;
52
+ private state;
53
+ private proc;
54
+ private bootstrapFile;
55
+ private lineBuffer;
56
+ private pending;
57
+ readonly createdAt: number;
58
+ jobsRun: number;
59
+ constructor(opts: WorkerOptions);
60
+ get currentState(): WorkerState;
61
+ get isIdle(): boolean;
62
+ /** Spawn the Deno subprocess. */
63
+ start(): Promise<void>;
64
+ /**
65
+ * Execute a job on this worker.
66
+ * The worker must be idle before calling this.
67
+ */
68
+ execute(job: WorkerJob): Promise<WorkerResult>;
69
+ /**
70
+ * Gracefully shut down the worker.
71
+ * If `drainFirst` is true, waits for any in-flight job to complete.
72
+ */
73
+ shutdown(drainFirst?: boolean): Promise<void>;
74
+ private _handleLine;
75
+ private _handleClose;
76
+ private _rejectAll;
77
+ private _terminate;
78
+ private _cleanup;
79
+ }
80
+ //# sourceMappingURL=worker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../src/runtime/pool/worker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,eAAe,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,mDAAmD;IACnD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AA4GjE,qBAAa,YAAY;IAcX,OAAO,CAAC,QAAQ,CAAC,IAAI;IAbjC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,KAAK,CAAuB;IACpC,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,UAAU,CAAM;IACxB,OAAO,CAAC,OAAO,CAGA;IAEf,QAAQ,CAAC,SAAS,SAAc;IAChC,OAAO,SAAK;gBAEiB,IAAI,EAAE,aAAa;IAIhD,IAAI,YAAY,IAAI,WAAW,CAE9B;IAED,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,iCAAiC;IAC3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA8D5B;;;OAGG;IACH,OAAO,CAAC,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC;IAoD9C;;;OAGG;IACG,QAAQ,CAAC,UAAU,UAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBhD,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,QAAQ;CAMjB"}
@@ -0,0 +1,324 @@
1
+ /**
2
+ * Individual Deno Worker Lifecycle
3
+ *
4
+ * Manages a single warm Deno worker subprocess. The worker runs a persistent
5
+ * bootstrap script that:
6
+ * 1. Accepts a list of preload helper scripts (Phase 5 plug-in point)
7
+ * 2. Waits for job messages on stdin, executes the code, returns results on stdout
8
+ *
9
+ * Communication protocol (newline-delimited JSON over stdio):
10
+ * host → worker: { id, code, context }
11
+ * worker → host: { id, success, result?, error?, logs }
12
+ *
13
+ * @module runtime/pool/worker
14
+ */
15
+ import { spawn } from 'node:child_process';
16
+ import { writeFileSync, unlinkSync } from 'node:fs';
17
+ import { join } from 'node:path';
18
+ import { tmpdir } from 'node:os';
19
+ import { logger, minimalChildEnv } from '../../utils/index.js';
20
+ // ─────────────────────────────────────────────────────────────────────────────
21
+ // Bootstrap script written to a temp file once per worker
22
+ // ─────────────────────────────────────────────────────────────────────────────
23
+ function buildBootstrapScript(opts) {
24
+ const preloads = (opts.preloadHelpers ?? [])
25
+ .map((p) => `await import(${JSON.stringify(p)});`)
26
+ .join('\n');
27
+ return `
28
+ // MCP Conductor — Warm Worker Bootstrap
29
+ // This script runs persistently inside a Deno subprocess.
30
+ // It receives jobs on stdin and returns results on stdout.
31
+
32
+ // Preload Phase-5 helpers when available
33
+ ${preloads}
34
+
35
+ const __bridgeUrl = ${JSON.stringify(opts.bridgeUrl ?? 'http://127.0.0.1:9847')};
36
+ const __logs: string[] = [];
37
+
38
+ // Override console.log to capture output
39
+ const __origLog = console.log;
40
+ console.log = (...args: unknown[]) => {
41
+ const msg = args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join(' ');
42
+ __logs.push(msg);
43
+ __origLog(...args);
44
+ };
45
+
46
+ // MCPServerClient — mirrors executor.ts sandbox runtime
47
+ class MCPServerClient {
48
+ constructor(public readonly name: string) {}
49
+ async call(tool: string, params: Record<string, unknown> = {}): Promise<unknown> {
50
+ const response = await fetch(\`\${__bridgeUrl}/call\`, {
51
+ method: 'POST',
52
+ headers: { 'Content-Type': 'application/json' },
53
+ body: JSON.stringify({ server: this.name, tool, params }),
54
+ });
55
+ const data = await response.json();
56
+ if (data.error) throw new Error(\`Tool error (\${this.name}.\${tool}): \${data.error.message}\`);
57
+ return data.result;
58
+ }
59
+ }
60
+
61
+ const __mcpBase = {
62
+ server(name: string) { return new MCPServerClient(name); },
63
+ log(...args: unknown[]) { console.log(...args); },
64
+ };
65
+ const mcp = new Proxy(__mcpBase, {
66
+ get(t, p) {
67
+ if (p in t) return (t as Record<string|symbol, unknown>)[p];
68
+ if (typeof p === 'string') return new MCPServerClient(p);
69
+ return undefined;
70
+ },
71
+ });
72
+
73
+ // Main job loop — read one JSON line per job
74
+ const decoder = new TextDecoder();
75
+ let buf = '';
76
+
77
+ async function processLine(line: string): Promise<void> {
78
+ let job: { id: string; code: string; context: Record<string, unknown> };
79
+ try {
80
+ job = JSON.parse(line);
81
+ } catch {
82
+ return; // malformed, skip
83
+ }
84
+
85
+ __logs.length = 0; // reset per job
86
+
87
+ let result: unknown;
88
+ let error: { message: string; stack?: string } | undefined;
89
+ let success = true;
90
+
91
+ try {
92
+ // Execute user code in an async wrapper with mcp in scope
93
+ const __fn = new Function('mcp', '__ctx', \`return (async () => { \${job.code} })()\`);
94
+ result = await __fn(mcp, job.context ?? {});
95
+ } catch (err: unknown) {
96
+ success = false;
97
+ const e = err as Error;
98
+ error = { message: e.message, stack: e.stack };
99
+ }
100
+
101
+ const response = JSON.stringify({ id: job.id, success, result, error, logs: [...__logs] });
102
+ __origLog(response); // use original console.log to avoid capture loop
103
+ }
104
+
105
+ // Read stdin line by line
106
+ for await (const chunk of Deno.stdin.readable) {
107
+ buf += decoder.decode(chunk);
108
+ let nl: number;
109
+ while ((nl = buf.indexOf('\\n')) !== -1) {
110
+ const line = buf.slice(0, nl).trim();
111
+ buf = buf.slice(nl + 1);
112
+ if (line) await processLine(line);
113
+ }
114
+ }
115
+ `;
116
+ }
117
+ // ─────────────────────────────────────────────────────────────────────────────
118
+ // PooledWorker
119
+ // ─────────────────────────────────────────────────────────────────────────────
120
+ let workerSeq = 0;
121
+ export class PooledWorker {
122
+ opts;
123
+ id;
124
+ state = 'idle';
125
+ proc = null;
126
+ bootstrapFile = null;
127
+ lineBuffer = '';
128
+ pending = new Map();
129
+ createdAt = Date.now();
130
+ jobsRun = 0;
131
+ constructor(opts) {
132
+ this.opts = opts;
133
+ this.id = `worker-${++workerSeq}-${Date.now()}`;
134
+ }
135
+ get currentState() {
136
+ return this.state;
137
+ }
138
+ get isIdle() {
139
+ return this.state === 'idle';
140
+ }
141
+ /** Spawn the Deno subprocess. */
142
+ async start() {
143
+ const script = buildBootstrapScript(this.opts);
144
+ const tmpPath = join(tmpdir(), `mcp-worker-${this.id}.ts`);
145
+ writeFileSync(tmpPath, script);
146
+ this.bootstrapFile = tmpPath;
147
+ const maxMemMb = this.opts.maxMemoryMb ?? 128;
148
+ const proc = spawn('deno', [
149
+ 'run',
150
+ '--allow-net',
151
+ '--allow-read',
152
+ '--no-prompt',
153
+ `--v8-flags=--max-old-space-size=${maxMemMb}`,
154
+ tmpPath,
155
+ ], {
156
+ stdio: ['pipe', 'pipe', 'pipe'],
157
+ env: minimalChildEnv({
158
+ DENO_DIR: process.env.DENO_DIR,
159
+ NO_COLOR: '1',
160
+ }),
161
+ });
162
+ this.proc = proc;
163
+ proc.stdout?.on('data', (chunk) => {
164
+ this.lineBuffer += chunk.toString('utf8');
165
+ let nl;
166
+ while ((nl = this.lineBuffer.indexOf('\n')) !== -1) {
167
+ const line = this.lineBuffer.slice(0, nl).trim();
168
+ this.lineBuffer = this.lineBuffer.slice(nl + 1);
169
+ if (line)
170
+ this._handleLine(line);
171
+ }
172
+ });
173
+ proc.stderr?.on('data', (chunk) => {
174
+ const text = chunk.toString('utf8').trim();
175
+ if (text) {
176
+ logger.debug('Worker stderr', { workerId: this.id, text: text.slice(0, 500) });
177
+ }
178
+ });
179
+ proc.on('close', (code) => {
180
+ this._handleClose(code ?? -1);
181
+ });
182
+ proc.on('error', (err) => {
183
+ logger.error('Worker spawn error', { workerId: this.id, err: err.message });
184
+ this._rejectAll(err);
185
+ this.state = 'dead';
186
+ });
187
+ // Brief pause to allow the Deno runtime to initialise before accepting jobs.
188
+ // This ensures the warm-up cost is paid at pool startup, not at first job.
189
+ await new Promise((resolve) => {
190
+ const t = setTimeout(resolve, 50);
191
+ if (t.unref)
192
+ t.unref();
193
+ });
194
+ logger.debug('Worker started', { workerId: this.id });
195
+ }
196
+ /**
197
+ * Execute a job on this worker.
198
+ * The worker must be idle before calling this.
199
+ */
200
+ execute(job) {
201
+ if (this.state !== 'idle') {
202
+ return Promise.reject(new Error(`Worker ${this.id} is not idle (state: ${this.state})`));
203
+ }
204
+ if (!this.proc?.stdin?.writable) {
205
+ return Promise.reject(new Error(`Worker ${this.id} stdin is not writable`));
206
+ }
207
+ this.state = 'busy';
208
+ this.jobsRun++;
209
+ return new Promise((resolve, reject) => {
210
+ // Honour AbortSignal cancellation
211
+ const onAbort = () => {
212
+ this.pending.delete(job.id);
213
+ this.state = 'idle';
214
+ reject(new Error('Job cancelled by AbortSignal'));
215
+ };
216
+ if (job.signal?.aborted) {
217
+ this.state = 'idle';
218
+ this.jobsRun--; // didn't actually run
219
+ onAbort();
220
+ return;
221
+ }
222
+ job.signal?.addEventListener('abort', onAbort, { once: true });
223
+ this.pending.set(job.id, {
224
+ resolve: (result) => {
225
+ job.signal?.removeEventListener('abort', onAbort);
226
+ this.state = 'idle';
227
+ resolve(result);
228
+ },
229
+ reject: (err) => {
230
+ job.signal?.removeEventListener('abort', onAbort);
231
+ this.state = 'idle';
232
+ reject(err);
233
+ },
234
+ });
235
+ const message = JSON.stringify({ id: job.id, code: job.code, context: job.context });
236
+ try {
237
+ this.proc.stdin.write(message + '\n');
238
+ }
239
+ catch (writeErr) {
240
+ this.pending.delete(job.id);
241
+ this.state = 'idle';
242
+ job.signal?.removeEventListener('abort', onAbort);
243
+ reject(writeErr instanceof Error ? writeErr : new Error(String(writeErr)));
244
+ }
245
+ });
246
+ }
247
+ /**
248
+ * Gracefully shut down the worker.
249
+ * If `drainFirst` is true, waits for any in-flight job to complete.
250
+ */
251
+ async shutdown(drainFirst = true) {
252
+ if (this.state === 'dead')
253
+ return;
254
+ if (drainFirst && this.state === 'busy') {
255
+ await new Promise((resolve) => {
256
+ const interval = setInterval(() => {
257
+ if (this.state !== 'busy') {
258
+ clearInterval(interval);
259
+ resolve();
260
+ }
261
+ }, 10);
262
+ });
263
+ }
264
+ this.state = 'recycling';
265
+ this._terminate();
266
+ }
267
+ // ─────────────────────────────────────────────────────────────────────────
268
+ // Private
269
+ // ─────────────────────────────────────────────────────────────────────────
270
+ _handleLine(line) {
271
+ let msg;
272
+ try {
273
+ msg = JSON.parse(line);
274
+ }
275
+ catch {
276
+ logger.warn('Worker: unparseable response', { workerId: this.id, line: line.slice(0, 200) });
277
+ return;
278
+ }
279
+ const pending = this.pending.get(msg.id);
280
+ if (pending) {
281
+ this.pending.delete(msg.id);
282
+ pending.resolve(msg);
283
+ }
284
+ }
285
+ _handleClose(code) {
286
+ this.state = 'dead';
287
+ this._cleanup();
288
+ this._rejectAll(new Error(`Worker ${this.id} exited with code ${code}`));
289
+ logger.debug('Worker exited', { workerId: this.id, code });
290
+ }
291
+ _rejectAll(err) {
292
+ for (const [, handlers] of this.pending) {
293
+ handlers.reject(err);
294
+ }
295
+ this.pending.clear();
296
+ }
297
+ _terminate() {
298
+ try {
299
+ this.proc?.kill('SIGTERM');
300
+ const t = setTimeout(() => {
301
+ try {
302
+ this.proc?.kill('SIGKILL');
303
+ }
304
+ catch { /* already gone */ }
305
+ }, 2000);
306
+ if (t.unref)
307
+ t.unref();
308
+ }
309
+ catch {
310
+ // Already dead
311
+ }
312
+ this._cleanup();
313
+ }
314
+ _cleanup() {
315
+ if (this.bootstrapFile) {
316
+ try {
317
+ unlinkSync(this.bootstrapFile);
318
+ }
319
+ catch { /* ignore */ }
320
+ this.bootstrapFile = null;
321
+ }
322
+ }
323
+ }
324
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../src/runtime/pool/worker.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export declare class MCPExecutorServer {
19
19
  private config;
20
20
  private useMockServers;
21
21
  private currentMode;
22
+ private registry;
22
23
  private mockServers;
23
24
  constructor(config: MCPExecutorConfig, options?: {
24
25
  useMockServers?: boolean;
@@ -30,6 +31,11 @@ export declare class MCPExecutorServer {
30
31
  /**
31
32
  * Register all MCP tools
32
33
  */
34
+ /**
35
+ * Record metrics + shape the execute_code tool response. Extracted so the
36
+ * progress/cancel wiring in the handler stays readable.
37
+ */
38
+ private finaliseExecuteCodeResult;
33
39
  private registerTools;
34
40
  /**
35
41
  * Start the server