@the-open-engine/zeroshot 6.38.1 → 6.39.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 (383) hide show
  1. package/README.md +6 -0
  2. package/cli/event-copy.js +8 -7
  3. package/cli/event-copy.ts +12 -0
  4. package/cli/index.js +67 -48
  5. package/cli/json-export.js +61 -64
  6. package/cli/json-export.ts +112 -0
  7. package/cli/message-formatter-utils.js +68 -56
  8. package/cli/message-formatter-utils.ts +121 -0
  9. package/cli/message-formatters-normal.js +124 -259
  10. package/cli/message-formatters-normal.ts +250 -0
  11. package/cli/message-formatters-watch.js +81 -84
  12. package/cli/message-formatters-watch.ts +189 -0
  13. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  14. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  15. package/lib/cluster/generated/protocol.d.cts +8 -0
  16. package/lib/cluster/generated/protocol.d.mts +8 -0
  17. package/lib/cluster/generated/protocol.d.ts +8 -0
  18. package/lib/clusters-registry.d.ts +23 -0
  19. package/lib/clusters-registry.js +17 -29
  20. package/lib/completion.d.ts +12 -0
  21. package/lib/completion.js +84 -94
  22. package/lib/compose-utils.d.ts +32 -0
  23. package/lib/compose-utils.js +57 -72
  24. package/lib/detached-startup.d.ts +84 -0
  25. package/lib/detached-startup.js +232 -302
  26. package/lib/docker-config.d.ts +43 -0
  27. package/lib/docker-config.js +150 -325
  28. package/lib/docker-env-auth.d.ts +17 -0
  29. package/lib/docker-env-auth.js +75 -0
  30. package/lib/git-remote-utils.d.ts +48 -0
  31. package/lib/git-remote-utils.js +147 -213
  32. package/lib/id-detector.d.ts +15 -0
  33. package/lib/id-detector.js +37 -41
  34. package/lib/path-check.d.ts +30 -0
  35. package/lib/path-check.js +42 -45
  36. package/lib/process-liveness.d.ts +16 -0
  37. package/lib/process-liveness.js +19 -12
  38. package/lib/provider-credential-path.d.ts +16 -0
  39. package/lib/provider-credential-path.js +31 -29
  40. package/lib/provider-defaults.d.ts +30 -0
  41. package/lib/provider-defaults.js +47 -42
  42. package/lib/provider-detection.d.ts +11 -0
  43. package/lib/provider-detection.js +91 -54
  44. package/lib/provider-names.d.ts +38 -0
  45. package/lib/provider-names.js +56 -64
  46. package/lib/repo-settings.d.ts +28 -0
  47. package/lib/repo-settings.js +83 -59
  48. package/lib/run-mode.d.ts +21 -0
  49. package/lib/run-mode.js +21 -20
  50. package/lib/run-plan.d.ts +28 -0
  51. package/lib/run-plan.js +17 -16
  52. package/lib/settings/claude-auth.d.ts +35 -0
  53. package/lib/settings/claude-auth.js +30 -47
  54. package/lib/settings-defaults.d.ts +20 -0
  55. package/lib/settings-defaults.js +149 -0
  56. package/lib/settings-error.d.ts +7 -0
  57. package/lib/settings-error.js +8 -0
  58. package/lib/settings-issue-providers.d.ts +10 -0
  59. package/lib/settings-issue-providers.js +12 -0
  60. package/lib/settings-models.d.ts +22 -0
  61. package/lib/settings-models.js +93 -0
  62. package/lib/settings-storage.d.ts +23 -0
  63. package/lib/settings-storage.js +205 -0
  64. package/lib/settings-validation.d.ts +7 -0
  65. package/lib/settings-validation.js +182 -0
  66. package/lib/settings.d.ts +29 -0
  67. package/lib/settings.js +41 -736
  68. package/lib/setup-apply-types.d.ts +66 -0
  69. package/lib/setup-apply-types.js +2 -0
  70. package/lib/setup-apply.d.ts +39 -0
  71. package/lib/setup-apply.js +267 -264
  72. package/lib/setup-journal.d.ts +41 -0
  73. package/lib/setup-journal.js +119 -76
  74. package/lib/setup-plan-types.d.ts +102 -0
  75. package/lib/setup-plan-types.js +2 -0
  76. package/lib/setup-plan.d.ts +30 -0
  77. package/lib/setup-plan.js +300 -324
  78. package/lib/setup-undo.d.ts +44 -0
  79. package/lib/setup-undo.js +61 -74
  80. package/lib/start-cluster-config.d.ts +26 -0
  81. package/lib/start-cluster-config.js +56 -0
  82. package/lib/start-cluster-environment.d.ts +41 -0
  83. package/lib/start-cluster-environment.js +134 -0
  84. package/lib/start-cluster-run-options.d.ts +54 -0
  85. package/lib/start-cluster-run-options.js +148 -0
  86. package/lib/start-cluster.d.ts +64 -0
  87. package/lib/start-cluster.js +98 -454
  88. package/lib/stream-json-parser.d.ts +17 -0
  89. package/lib/stream-json-parser.js +51 -52
  90. package/npm-shrinkwrap.json +6 -8
  91. package/package.json +14 -8
  92. package/scripts/postinstall.js +27 -0
  93. package/scripts/rust-distribution.js +36 -45
  94. package/src/agent/agent-command-proofs-context.js +35 -45
  95. package/src/agent/agent-command-proofs-context.ts +87 -0
  96. package/src/agent/agent-config-settings.js +19 -0
  97. package/src/agent/agent-config-settings.ts +41 -0
  98. package/src/agent/agent-config.js +122 -231
  99. package/src/agent/agent-config.ts +285 -0
  100. package/src/agent/agent-context-builder.js +38 -273
  101. package/src/agent/agent-context-builder.ts +51 -0
  102. package/src/agent/agent-context-environment-sections.js +105 -0
  103. package/src/agent/agent-context-environment-sections.ts +134 -0
  104. package/src/agent/agent-context-packs.js +165 -0
  105. package/src/agent/agent-context-packs.ts +296 -0
  106. package/src/agent/agent-context-prompt-sections.js +100 -0
  107. package/src/agent/agent-context-prompt-sections.ts +148 -0
  108. package/src/agent/agent-context-sections.js +25 -334
  109. package/src/agent/agent-context-sections.ts +36 -0
  110. package/src/agent/agent-context-sources.js +96 -149
  111. package/src/agent/agent-context-sources.ts +253 -0
  112. package/src/agent/agent-context-types.js +2 -0
  113. package/src/agent/agent-context-types.ts +132 -0
  114. package/src/agent/agent-context-validation-sections.js +73 -0
  115. package/src/agent/agent-context-validation-sections.ts +129 -0
  116. package/src/agent/agent-input-injector.js +99 -118
  117. package/src/agent/agent-input-injector.ts +195 -0
  118. package/src/agent/agent-liveness-poll.js +74 -78
  119. package/src/agent/agent-liveness-poll.ts +163 -0
  120. package/src/agent/agent-quality-gate-schema.js +77 -86
  121. package/src/agent/agent-quality-gate-schema.ts +135 -0
  122. package/src/agent/agent-quality-gates-context.js +44 -50
  123. package/src/agent/agent-quality-gates-context.ts +91 -0
  124. package/src/agent/agent-stuck-detector.js +171 -239
  125. package/src/agent/agent-stuck-detector.ts +288 -0
  126. package/src/agent/agent-trigger-evaluator.js +29 -46
  127. package/src/agent/agent-trigger-evaluator.ts +98 -0
  128. package/src/agent/context-metrics.js +110 -141
  129. package/src/agent/context-metrics.ts +261 -0
  130. package/src/agent/context-pack-builder.js +72 -358
  131. package/src/agent/context-pack-builder.ts +105 -0
  132. package/src/agent/context-pack-core.js +70 -0
  133. package/src/agent/context-pack-core.ts +96 -0
  134. package/src/agent/context-pack-selection.js +119 -0
  135. package/src/agent/context-pack-selection.ts +187 -0
  136. package/src/agent/context-pack-truncation.js +139 -0
  137. package/src/agent/context-pack-truncation.ts +208 -0
  138. package/src/agent/context-pack-types.js +2 -0
  139. package/src/agent/context-pack-types.ts +98 -0
  140. package/src/agent/context-replay-policy.js +30 -39
  141. package/src/agent/context-replay-policy.ts +71 -0
  142. package/src/agent/critical-agent-policy.js +6 -10
  143. package/src/agent/critical-agent-policy.ts +20 -0
  144. package/src/agent/guidance-queue.js +74 -87
  145. package/src/agent/guidance-queue.ts +166 -0
  146. package/src/agent/output-extraction-error-detail.js +45 -0
  147. package/src/agent/output-extraction-error-detail.ts +49 -0
  148. package/src/agent/output-extraction-failures.js +125 -0
  149. package/src/agent/output-extraction-failures.ts +149 -0
  150. package/src/agent/output-extraction-json.js +234 -0
  151. package/src/agent/output-extraction-json.ts +235 -0
  152. package/src/agent/output-extraction-pi.js +124 -0
  153. package/src/agent/output-extraction-pi.ts +137 -0
  154. package/src/agent/output-extraction-types.js +2 -0
  155. package/src/agent/output-extraction-types.ts +49 -0
  156. package/src/agent/output-extraction.js +17 -617
  157. package/src/agent/output-extraction.ts +30 -0
  158. package/src/agent/output-reformatter-errors.js +83 -0
  159. package/src/agent/output-reformatter-errors.ts +106 -0
  160. package/src/agent/output-reformatter-types.js +2 -0
  161. package/src/agent/output-reformatter-types.ts +86 -0
  162. package/src/agent/output-reformatter.js +140 -185
  163. package/src/agent/output-reformatter.ts +238 -0
  164. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  165. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  166. package/src/agent/pi-terminal-lifecycle.js +186 -206
  167. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  168. package/src/agent/provider-control-plane.js +22 -21
  169. package/src/agent/provider-control-plane.ts +52 -0
  170. package/src/agent/provider-terminal-failure-types.js +2 -0
  171. package/src/agent/provider-terminal-failure-types.ts +60 -0
  172. package/src/agent/provider-terminal-failure.js +194 -191
  173. package/src/agent/provider-terminal-failure.ts +262 -0
  174. package/src/agent/rate-limit-backoff.js +31 -74
  175. package/src/agent/rate-limit-backoff.ts +71 -0
  176. package/src/agent/schema-utils.js +85 -125
  177. package/src/agent/schema-utils.ts +148 -0
  178. package/src/agent/structured-output-error.js +34 -33
  179. package/src/agent/structured-output-error.ts +105 -0
  180. package/src/agent/validation-platform.js +27 -27
  181. package/src/agent/validation-platform.ts +49 -0
  182. package/src/agents/git-pusher-template.js +17 -34
  183. package/src/attach/attach-client.js +232 -405
  184. package/src/attach/attach-client.ts +300 -0
  185. package/src/attach/attach-server-cleanup.js +43 -0
  186. package/src/attach/attach-server-cleanup.ts +39 -0
  187. package/src/attach/attach-server-clients.js +117 -0
  188. package/src/attach/attach-server-clients.ts +122 -0
  189. package/src/attach/attach-server-events.js +38 -0
  190. package/src/attach/attach-server-events.ts +36 -0
  191. package/src/attach/attach-server-pty.js +45 -0
  192. package/src/attach/attach-server-pty.ts +64 -0
  193. package/src/attach/attach-server-runtime.js +73 -0
  194. package/src/attach/attach-server-runtime.ts +62 -0
  195. package/src/attach/attach-server-socket.js +28 -0
  196. package/src/attach/attach-server-socket.ts +23 -0
  197. package/src/attach/attach-server-types.js +2 -0
  198. package/src/attach/attach-server-types.ts +82 -0
  199. package/src/attach/attach-server.js +106 -523
  200. package/src/attach/attach-server.ts +158 -0
  201. package/src/attach/index.js +18 -35
  202. package/src/attach/index.ts +18 -0
  203. package/src/attach/protocol.js +95 -184
  204. package/src/attach/protocol.ts +181 -0
  205. package/src/attach/ring-buffer.js +76 -102
  206. package/src/attach/ring-buffer.ts +109 -0
  207. package/src/attach/send-input.js +64 -75
  208. package/src/attach/send-input.ts +94 -0
  209. package/src/attach/socket-discovery.js +164 -218
  210. package/src/attach/socket-discovery.ts +230 -0
  211. package/src/attach/socket-paths.js +42 -61
  212. package/src/attach/socket-paths.ts +81 -0
  213. package/src/claude-credentials.js +51 -54
  214. package/src/claude-credentials.ts +89 -0
  215. package/src/cluster/generated/protocol-schema.ts +1 -1
  216. package/src/cluster/generated/protocol.ts +2 -1
  217. package/src/command-proofs.js +110 -141
  218. package/src/command-proofs.ts +216 -0
  219. package/src/config-router.js +81 -73
  220. package/src/config-router.ts +131 -0
  221. package/src/copy-containment.js +191 -0
  222. package/src/copy-containment.ts +259 -0
  223. package/src/copy-worker.js +53 -30
  224. package/src/copy-worker.ts +88 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/isolation-manager.js +59 -20
  232. package/src/ledger-sequence.js +45 -48
  233. package/src/ledger-sequence.ts +63 -0
  234. package/src/legacy-lib/clusters-registry.ts +40 -0
  235. package/src/legacy-lib/completion.ts +148 -0
  236. package/src/legacy-lib/compose-utils.ts +102 -0
  237. package/src/legacy-lib/detached-startup.ts +451 -0
  238. package/src/legacy-lib/docker-config.ts +282 -0
  239. package/src/legacy-lib/docker-env-auth.ts +116 -0
  240. package/src/legacy-lib/git-remote-utils.ts +244 -0
  241. package/src/legacy-lib/id-detector.ts +57 -0
  242. package/src/legacy-lib/js-yaml.d.ts +3 -0
  243. package/src/legacy-lib/omelette.d.ts +15 -0
  244. package/src/legacy-lib/path-check.ts +89 -0
  245. package/src/legacy-lib/process-liveness.ts +36 -0
  246. package/src/legacy-lib/provider-credential-path.ts +57 -0
  247. package/src/legacy-lib/provider-defaults.ts +114 -0
  248. package/src/legacy-lib/provider-detection.ts +67 -0
  249. package/src/legacy-lib/provider-names.ts +126 -0
  250. package/src/legacy-lib/repo-settings.ts +88 -0
  251. package/src/legacy-lib/run-mode.ts +58 -0
  252. package/src/legacy-lib/run-plan.ts +49 -0
  253. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  254. package/src/legacy-lib/settings-defaults.ts +212 -0
  255. package/src/legacy-lib/settings-error.ts +8 -0
  256. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  257. package/src/legacy-lib/settings-models.ts +124 -0
  258. package/src/legacy-lib/settings-storage.ts +277 -0
  259. package/src/legacy-lib/settings-validation.ts +220 -0
  260. package/src/legacy-lib/settings.ts +87 -0
  261. package/src/legacy-lib/setup-apply-types.ts +70 -0
  262. package/src/legacy-lib/setup-apply.ts +456 -0
  263. package/src/legacy-lib/setup-journal.ts +185 -0
  264. package/src/legacy-lib/setup-plan-types.ts +96 -0
  265. package/src/legacy-lib/setup-plan.ts +500 -0
  266. package/src/legacy-lib/setup-undo.ts +142 -0
  267. package/src/legacy-lib/start-cluster-config.ts +124 -0
  268. package/src/legacy-lib/start-cluster-environment.ts +166 -0
  269. package/src/legacy-lib/start-cluster-run-options.ts +281 -0
  270. package/src/legacy-lib/start-cluster.ts +237 -0
  271. package/src/legacy-lib/stream-json-parser.ts +88 -0
  272. package/src/message-buffer.js +55 -71
  273. package/src/message-buffer.ts +107 -0
  274. package/src/message-bus-bridge.js +92 -133
  275. package/src/message-bus-bridge.ts +149 -0
  276. package/src/name-generator-shared.js +220 -0
  277. package/src/name-generator-shared.ts +231 -0
  278. package/src/name-generator.js +8 -217
  279. package/src/name-generator.ts +27 -0
  280. package/src/omp-blob-root.js +83 -64
  281. package/src/omp-blob-root.ts +116 -0
  282. package/src/omp-config-overlay.js +65 -38
  283. package/src/omp-config-overlay.ts +110 -0
  284. package/src/omp-execution-fingerprint.js +38 -43
  285. package/src/omp-execution-fingerprint.ts +92 -0
  286. package/src/omp-session-limits.js +10 -15
  287. package/src/omp-session-limits.ts +53 -0
  288. package/src/omp-session-partition.js +2 -2
  289. package/src/omp-session-verifier.js +1 -1
  290. package/src/orchestrator.js +32 -7
  291. package/src/pr-body-template.js +71 -0
  292. package/src/providers/anthropic/index.js +3 -1
  293. package/src/providers/anthropic/index.ts +13 -0
  294. package/src/providers/capabilities.js +19 -27
  295. package/src/providers/capabilities.ts +44 -0
  296. package/src/providers/google/index.js +3 -1
  297. package/src/providers/google/index.ts +13 -0
  298. package/src/providers/openai/index.js +3 -1
  299. package/src/providers/openai/index.ts +13 -0
  300. package/src/providers/opencode/index.js +3 -1
  301. package/src/providers/opencode/index.ts +13 -0
  302. package/src/quality-gates.js +67 -127
  303. package/src/quality-gates.ts +149 -0
  304. package/src/repo-settings-access.js +40 -0
  305. package/src/repo-settings-access.ts +64 -0
  306. package/src/schemas/sub-cluster.js +127 -183
  307. package/src/schemas/sub-cluster.ts +238 -0
  308. package/src/state-snapshot-normalization.js +224 -0
  309. package/src/state-snapshot-normalization.ts +222 -0
  310. package/src/state-snapshot.js +192 -359
  311. package/src/state-snapshot.ts +291 -0
  312. package/src/state-snapshotter.js +118 -130
  313. package/src/state-snapshotter.ts +167 -0
  314. package/src/sub-cluster-wrapper.js +4 -13
  315. package/src/task-run-model-args.js +87 -124
  316. package/src/task-run-model-args.ts +204 -0
  317. package/src/task-runner.js +5 -25
  318. package/src/task-runner.ts +28 -0
  319. package/src/task-startup-error.js +73 -58
  320. package/src/task-startup-error.ts +126 -0
  321. package/src/template-validation/consensus-gate-contracts.js +2 -0
  322. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  323. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  324. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  325. package/src/template-validation/consensus-gate-stage.js +34 -0
  326. package/src/template-validation/consensus-gate-stage.ts +56 -0
  327. package/src/template-validation/random-topology-contracts.js +2 -0
  328. package/src/template-validation/random-topology-contracts.ts +54 -0
  329. package/src/template-validation/random-topology-dispatch.js +25 -0
  330. package/src/template-validation/random-topology-dispatch.ts +33 -0
  331. package/src/template-validation/random-topology-message-loop.js +53 -0
  332. package/src/template-validation/random-topology-message-loop.ts +73 -0
  333. package/src/template-validation/random-topology-operations.js +79 -0
  334. package/src/template-validation/random-topology-operations.ts +101 -0
  335. package/src/template-validation/random-topology-runtime.js +25 -0
  336. package/src/template-validation/random-topology-runtime.ts +43 -0
  337. package/src/template-validation/random-topology-scenario.js +52 -0
  338. package/src/template-validation/random-topology-scenario.ts +57 -0
  339. package/src/template-validation/random-topology-schema.js +159 -0
  340. package/src/template-validation/random-topology-schema.ts +190 -0
  341. package/src/template-validation/random-topology-state.js +28 -0
  342. package/src/template-validation/random-topology-state.ts +30 -0
  343. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  344. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  345. package/src/template-validation/random-topology-trigger.js +75 -0
  346. package/src/template-validation/random-topology-trigger.ts +88 -0
  347. package/src/template-validation/report-formatter.js +40 -46
  348. package/src/template-validation/report-formatter.ts +101 -0
  349. package/src/template-validation/simulate-consensus-gates.js +111 -302
  350. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  351. package/src/template-validation/simulate-random-topology.js +26 -519
  352. package/src/template-validation/simulate-random-topology.ts +57 -0
  353. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  354. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  355. package/src/template-validation/simulation-agent-runtime.js +25 -0
  356. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  357. package/src/template-validation/simulation-agent.js +29 -0
  358. package/src/template-validation/simulation-agent.ts +73 -0
  359. package/src/template-validation/simulation-runtime.js +34 -0
  360. package/src/template-validation/simulation-runtime.ts +72 -0
  361. package/src/template-validation/two-stage-contracts.js +2 -0
  362. package/src/template-validation/two-stage-contracts.ts +41 -0
  363. package/src/template-validation/two-stage-inputs.js +21 -0
  364. package/src/template-validation/two-stage-inputs.ts +29 -0
  365. package/src/template-validation/two-stage-results.js +30 -0
  366. package/src/template-validation/two-stage-results.ts +40 -0
  367. package/src/template-validation/two-stage-scenario.js +86 -0
  368. package/src/template-validation/two-stage-scenario.ts +120 -0
  369. package/src/worktree-claude-config.js +182 -220
  370. package/src/worktree-claude-config.ts +272 -0
  371. package/src/worktree-tooling-env.js +103 -125
  372. package/src/worktree-tooling-env.ts +142 -0
  373. package/task-lib/completion.js +2 -3
  374. package/task-lib/completion.ts +9 -0
  375. package/task-lib/config.js +1 -4
  376. package/task-lib/config.ts +11 -0
  377. package/task-lib/name-generator.js +4 -226
  378. package/task-lib/name-generator.ts +11 -0
  379. package/task-lib/omp-session-cleanup.js +1 -1
  380. package/task-lib/omp-storage-root.js +8 -12
  381. package/task-lib/omp-storage-root.ts +62 -0
  382. package/task-lib/process-termination.js +143 -166
  383. package/task-lib/process-termination.ts +268 -0
@@ -1,543 +1,126 @@
1
- /**
2
- * AttachServer - PTY process manager with socket server for attach/detach
3
- *
4
- * Lifecycle:
5
- * 1. Created when task/agent spawns
6
- * 2. Spawns command via node-pty
7
- * 3. Listens on Unix socket for client connections
8
- * 4. Buffers output in ring buffer (for late-joining clients)
9
- * 5. Broadcasts output to all connected clients
10
- * 6. Cleans up when process exits
11
- *
12
- * Features:
13
- * - Multi-client support (multiple terminals can attach)
14
- * - Output history replay on attach
15
- * - Signal forwarding (SIGINT, SIGTERM)
16
- * - Window resize support
17
- * - Graceful cleanup on exit
18
- */
19
-
20
- const net = require('net');
21
- const fs = require('fs');
22
- const path = require('path');
23
- const EventEmitter = require('events');
24
-
25
- const RingBuffer = require('./ring-buffer');
26
- const protocol = require('./protocol');
27
- const { cleanupStaleSocket } = require('./socket-discovery');
28
-
29
- // FAIL FAST: Check for node-pty at module load time, not at spawn time
30
- let pty;
31
- try {
32
- pty = require('node-pty');
33
- } catch (e) {
34
- throw new Error(
35
- `AttachServer: node-pty not installed. Run: npm install node-pty\n` +
36
- `Original error: ${e.message}`
37
- );
38
- }
39
-
40
- // Default output buffer size: 1MB
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ const node_events_1 = require("node:events");
6
+ const node_fs_1 = __importDefault(require("node:fs"));
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const ring_buffer_1 = __importDefault(require("./ring-buffer"));
9
+ const socket_discovery_1 = __importDefault(require("./socket-discovery"));
10
+ const attach_server_clients_1 = require("./attach-server-clients");
11
+ const attach_server_cleanup_1 = require("./attach-server-cleanup");
12
+ const attach_server_events_1 = require("./attach-server-events");
13
+ const attach_server_pty_1 = require("./attach-server-pty");
14
+ const attach_server_runtime_1 = require("./attach-server-runtime");
15
+ const attach_server_socket_1 = require("./attach-server-socket");
41
16
  const DEFAULT_BUFFER_SIZE = 1024 * 1024;
42
-
43
- class AttachServer extends EventEmitter {
44
- /**
45
- * @param {object} options
46
- * @param {string} options.id - Task or agent ID
47
- * @param {string} options.socketPath - Unix socket path
48
- * @param {string} options.command - Command to spawn
49
- * @param {string[]} options.args - Command arguments
50
- * @param {string} [options.cwd] - Working directory
51
- * @param {object} [options.env] - Environment variables
52
- * @param {number} [options.cols] - Terminal columns (default 120)
53
- * @param {number} [options.rows] - Terminal rows (default 30)
54
- * @param {number} [options.bufferSize] - Output buffer size (default 1MB)
55
- */
56
- constructor(options) {
57
- super();
58
-
59
- if (!options.id) throw new Error('AttachServer: id is required');
60
- if (!options.socketPath) throw new Error('AttachServer: socketPath is required');
61
- if (!options.command) throw new Error('AttachServer: command is required');
62
-
63
- this.id = options.id;
64
- this.socketPath = options.socketPath;
65
- this.command = options.command;
66
- this.args = options.args || [];
67
- this.cwd = options.cwd || process.cwd();
68
- this.env = options.env || process.env;
69
- this.cols = options.cols || 120;
70
- this.rows = options.rows || 30;
71
-
72
- this.outputBuffer = new RingBuffer(options.bufferSize || DEFAULT_BUFFER_SIZE);
73
- this.clients = new Map(); // clientId -> { socket, decoder }
74
- this.pty = null;
75
- this.server = null;
76
- this.state = 'stopped'; // stopped, starting, running, exiting, exited
77
- this.exitCode = null;
78
- this.exitSignal = null;
79
- this.pid = null;
80
-
81
- // Bind cleanup handlers
82
- this._onProcessExit = this._onProcessExit.bind(this);
83
- this._onServerError = this._onServerError.bind(this);
84
- }
85
-
86
- /**
87
- * Start the PTY process and socket server
88
- * @returns {Promise<void>}
89
- */
90
- async start() {
91
- if (this.state !== 'stopped') {
92
- throw new Error(`AttachServer: Cannot start from state '${this.state}'`);
93
- }
94
-
95
- this.state = 'starting';
96
-
97
- // Ensure socket directory exists
98
- const socketDir = path.dirname(this.socketPath);
99
- if (!fs.existsSync(socketDir)) {
100
- fs.mkdirSync(socketDir, { recursive: true });
101
- }
102
-
103
- // Clean up stale socket if exists
104
- await cleanupStaleSocket(this.socketPath);
105
-
106
- // Check if socket is still in use (another process)
107
- if (fs.existsSync(this.socketPath)) {
108
- throw new Error(`AttachServer: Socket already in use: ${this.socketPath}`);
109
- }
110
-
111
- // Start socket server FIRST (so clients can connect immediately)
112
- await this._startServer();
113
-
114
- // Spawn PTY process
115
- await this._spawnPty();
116
-
117
- this.state = 'running';
118
- this.emit('start', { id: this.id, pid: this.pid });
119
- }
120
-
121
- /**
122
- * Stop the server and kill the PTY process
123
- * @param {string} [signal='SIGTERM'] - Signal to send
124
- * @returns {Promise<void>}
125
- */
126
- async stop(signal = 'SIGTERM') {
127
- if (this.state !== 'running') {
128
- return;
129
- }
130
-
131
- this.state = 'exiting';
132
-
133
- // Kill PTY process
134
- if (this.pty) {
135
- try {
136
- this.pty.kill(signal);
137
- } catch {
138
- // Process may already be dead
139
- }
140
- }
141
-
142
- // Wait for process to exit (with timeout)
143
- await new Promise((resolve) => {
144
- const timeout = setTimeout(() => {
145
- // Force kill if still running
146
- if (this.pty) {
147
- try {
148
- this.pty.kill('SIGKILL');
149
- } catch {
150
- // Ignore
151
- }
17
+ const { cleanupStaleSocket } = socket_discovery_1.default;
18
+ class AttachServer extends node_events_1.EventEmitter {
19
+ id;
20
+ socketPath;
21
+ command;
22
+ args;
23
+ cwd;
24
+ env;
25
+ cols;
26
+ rows;
27
+ outputBuffer;
28
+ clients = new Map();
29
+ pty = null;
30
+ server = null;
31
+ state = 'stopped';
32
+ exitCode = null;
33
+ exitSignal = null;
34
+ pid = null;
35
+ constructor(options) {
36
+ super();
37
+ if (!options.id)
38
+ throw new Error('AttachServer: id is required');
39
+ if (!options.socketPath)
40
+ throw new Error('AttachServer: socketPath is required');
41
+ if (!options.command)
42
+ throw new Error('AttachServer: command is required');
43
+ this.id = options.id;
44
+ this.socketPath = options.socketPath;
45
+ this.command = options.command;
46
+ this.args = options.args || [];
47
+ this.cwd = options.cwd || process.cwd();
48
+ this.env = options.env || process.env;
49
+ this.cols = options.cols || 120;
50
+ this.rows = options.rows || 30;
51
+ this.outputBuffer = new ring_buffer_1.default(options.bufferSize || DEFAULT_BUFFER_SIZE);
52
+ this._onProcessExit = this._onProcessExit.bind(this);
53
+ this._onServerError = this._onServerError.bind(this);
54
+ }
55
+ async start() {
56
+ if (this.state !== 'stopped') {
57
+ throw new Error(`AttachServer: Cannot start from state '${this.state}'`);
152
58
  }
153
- resolve();
154
- }, 5000);
155
-
156
- const checkExit = () => {
157
- if (this.state === 'exited') {
158
- clearTimeout(timeout);
159
- resolve();
160
- } else {
161
- setTimeout(checkExit, 100);
59
+ this.state = 'starting';
60
+ const socketDir = node_path_1.default.dirname(this.socketPath);
61
+ if (!node_fs_1.default.existsSync(socketDir))
62
+ node_fs_1.default.mkdirSync(socketDir, { recursive: true });
63
+ await cleanupStaleSocket(this.socketPath);
64
+ if (node_fs_1.default.existsSync(this.socketPath)) {
65
+ throw new Error(`AttachServer: Socket already in use: ${this.socketPath}`);
162
66
  }
163
- };
164
- checkExit();
165
- });
166
-
167
- await this._cleanup();
168
- }
169
-
170
- /**
171
- * Send a signal to the PTY process
172
- * @param {string} signal - Signal name (SIGINT, SIGTERM, etc.)
173
- */
174
- sendSignal(signal) {
175
- if (!this.pty || this.state !== 'running') {
176
- return false;
67
+ await this._startServer();
68
+ await this._spawnPty();
69
+ this.state = 'running';
70
+ this.emit('start', { id: this.id, pid: this.pid });
177
71
  }
178
-
179
- try {
180
- this.pty.kill(signal);
181
- return true;
182
- } catch {
183
- return false;
72
+ async stop(signal = 'SIGTERM') {
73
+ await (0, attach_server_runtime_1.stopPty)(this, signal);
184
74
  }
185
- }
186
-
187
- /**
188
- * Resize the PTY
189
- * @param {number} cols - Columns
190
- * @param {number} rows - Rows
191
- */
192
- resize(cols, rows) {
193
- if (!this.pty || this.state !== 'running') {
194
- return;
75
+ sendSignal(signal) {
76
+ return (0, attach_server_runtime_1.sendPtySignal)(this, signal);
195
77
  }
196
-
197
- this.cols = cols;
198
- this.rows = rows;
199
-
200
- try {
201
- this.pty.resize(cols, rows);
202
- } catch {
203
- // Ignore resize errors
78
+ resize(cols, rows) {
79
+ (0, attach_server_runtime_1.resizePty)(this, cols, rows);
204
80
  }
205
- }
206
-
207
- /**
208
- * Write to PTY stdin (for future interactive mode)
209
- * @param {Buffer|string} data - Data to write
210
- */
211
- write(data) {
212
- if (!this.pty || this.state !== 'running') {
213
- return false;
81
+ write(data) {
82
+ return (0, attach_server_runtime_1.writePty)(this, data);
214
83
  }
215
-
216
- try {
217
- this.pty.write(data);
218
- return true;
219
- } catch {
220
- return false;
84
+ getState() {
85
+ return {
86
+ id: this.id,
87
+ state: this.state,
88
+ pid: this.pid,
89
+ exitCode: this.exitCode,
90
+ exitSignal: this.exitSignal,
91
+ clientCount: this.clients.size,
92
+ bufferSize: this.outputBuffer.getSize(),
93
+ };
221
94
  }
222
- }
223
-
224
- /**
225
- * Get current server state
226
- * @returns {object}
227
- */
228
- getState() {
229
- return {
230
- id: this.id,
231
- state: this.state,
232
- pid: this.pid,
233
- exitCode: this.exitCode,
234
- exitSignal: this.exitSignal,
235
- clientCount: this.clients.size,
236
- bufferSize: this.outputBuffer.getSize(),
237
- };
238
- }
239
-
240
- // ─────────────────────────────────────────────────────────────────
241
- // Private methods
242
- // ─────────────────────────────────────────────────────────────────
243
-
244
- /**
245
- * Start the Unix socket server
246
- * @private
247
- */
248
- _startServer() {
249
- return new Promise((resolve, reject) => {
250
- this.server = net.createServer((socket) => {
251
- this._handleClientConnection(socket);
252
- });
253
-
254
- this.server.on('error', this._onServerError);
255
-
256
- this.server.listen(this.socketPath, () => {
257
- // Set socket permissions (owner read/write only)
258
- try {
259
- fs.chmodSync(this.socketPath, 0o600);
260
- } catch {
261
- // Ignore permission errors
262
- }
263
- resolve();
264
- });
265
-
266
- this.server.on('error', (err) => {
267
- if (this.state === 'starting') {
268
- reject(err);
269
- }
270
- });
271
- });
272
- }
273
-
274
- /**
275
- * Spawn the PTY process
276
- * @private
277
- */
278
- _spawnPty() {
279
- this.pty = pty.spawn(this.command, this.args, {
280
- name: 'xterm-256color',
281
- cols: this.cols,
282
- rows: this.rows,
283
- cwd: this.cwd,
284
- env: this.env,
285
- });
286
-
287
- this.pid = this.pty.pid;
288
-
289
- // Handle PTY output
290
- this.pty.onData((data) => {
291
- this._handlePtyOutput(data);
292
- });
293
-
294
- // Handle PTY exit
295
- this.pty.onExit(({ exitCode, signal }) => {
296
- this._onProcessExit(exitCode, signal);
297
- });
298
- }
299
-
300
- /**
301
- * Handle PTY output
302
- * @private
303
- */
304
- _handlePtyOutput(data) {
305
- // Buffer output for late-joining clients
306
- this.outputBuffer.write(data);
307
-
308
- // Broadcast to all connected clients
309
- const message = protocol.encode(protocol.createOutputMessage(data));
310
-
311
- for (const [clientId, client] of this.clients) {
312
- try {
313
- client.socket.write(message);
314
- } catch {
315
- // Client disconnected, will be cleaned up
316
- this._removeClient(clientId);
317
- }
95
+ _startServer() {
96
+ return (0, attach_server_socket_1.startSocketServer)(this);
318
97
  }
319
-
320
- // Emit for local listeners (e.g., logging)
321
- this.emit('output', data);
322
- }
323
-
324
- /**
325
- * Handle new client connection
326
- * @private
327
- */
328
- _handleClientConnection(socket) {
329
- const decoder = new protocol.MessageDecoder();
330
- let clientId = null;
331
-
332
- socket.on('data', (data) => {
333
- try {
334
- const messages = decoder.feed(data);
335
- for (const msg of messages) {
336
- this._handleClientMessage(socket, msg, (id) => {
337
- clientId = id;
338
- });
339
- }
340
- } catch (e) {
341
- // Protocol error, close connection
342
- this._sendError(socket, `Protocol error: ${e.message}`);
343
- socket.end();
344
- }
345
- });
346
-
347
- socket.on('close', () => {
348
- if (clientId) {
349
- this._removeClient(clientId);
350
- }
351
- });
352
-
353
- socket.on('error', () => {
354
- if (clientId) {
355
- this._removeClient(clientId);
356
- }
357
- });
358
- }
359
-
360
- /**
361
- * Handle message from client
362
- * @private
363
- */
364
- _handleClientMessage(socket, message, setClientId) {
365
- switch (message.type) {
366
- case protocol.MessageType.ATTACH: {
367
- const { clientId, cols, rows } = message;
368
- if (!clientId) {
369
- this._sendError(socket, 'ATTACH requires clientId');
370
- return;
371
- }
372
-
373
- // Register client
374
- this.clients.set(clientId, {
375
- socket,
376
- decoder: new protocol.MessageDecoder(),
377
- });
378
- setClientId(clientId);
379
-
380
- // Send history (buffered output)
381
- const history = this.outputBuffer.read();
382
- if (history.length > 0) {
383
- socket.write(protocol.encode(protocol.createHistoryMessage(history)));
384
- }
385
-
386
- // Send current state
387
- socket.write(protocol.encode(protocol.createStateMessage(this.getState())));
388
-
389
- // Resize PTY to client dimensions (if provided)
390
- if (cols && rows) {
391
- this.resize(cols, rows);
392
- }
393
-
394
- this.emit('clientAttach', { clientId });
395
- break;
396
- }
397
-
398
- case protocol.MessageType.DETACH: {
399
- const { clientId } = message;
400
- this._removeClient(clientId);
401
- socket.end();
402
- break;
403
- }
404
-
405
- case protocol.MessageType.RESIZE: {
406
- const { cols, rows } = message;
407
- if (cols && rows) {
408
- this.resize(cols, rows);
409
- }
410
- break;
411
- }
412
-
413
- case protocol.MessageType.SIGNAL: {
414
- const { signal } = message;
415
- this.sendSignal(signal);
416
- break;
417
- }
418
-
419
- case protocol.MessageType.STDIN: {
420
- // Future interactive mode
421
- const data = protocol.decodeData(message);
422
- if (data) {
423
- this.write(data);
424
- }
425
- break;
426
- }
427
-
428
- default:
429
- this._sendError(socket, `Unknown message type: ${message.type}`);
98
+ _spawnPty() {
99
+ (0, attach_server_pty_1.spawnPty)(this);
430
100
  }
431
- }
432
-
433
- /**
434
- * Remove a client
435
- * @private
436
- */
437
- _removeClient(clientId) {
438
- const client = this.clients.get(clientId);
439
- if (client) {
440
- this.clients.delete(clientId);
441
- this.emit('clientDetach', { clientId });
101
+ _handlePtyOutput(data) {
102
+ (0, attach_server_events_1.handlePtyOutput)(this, data);
442
103
  }
443
- }
444
-
445
- /**
446
- * Send error message to client
447
- * @private
448
- */
449
- _sendError(socket, message) {
450
- try {
451
- socket.write(protocol.encode(protocol.createErrorMessage(message)));
452
- } catch {
453
- // Client disconnected
104
+ _handleClientConnection(socket) {
105
+ (0, attach_server_clients_1.handleClientConnection)(this, socket);
454
106
  }
455
- }
456
-
457
- /**
458
- * Handle PTY process exit
459
- * @private
460
- */
461
- _onProcessExit(exitCode, signal) {
462
- this.exitCode = exitCode;
463
- this.exitSignal = signal;
464
- this.state = 'exited';
465
-
466
- // Notify all clients
467
- const exitMessage = protocol.encode(protocol.createExitMessage(exitCode, signal));
468
-
469
- for (const [, client] of this.clients) {
470
- try {
471
- client.socket.write(exitMessage);
472
- client.socket.end();
473
- } catch {
474
- // Client already disconnected
475
- }
107
+ _handleClientMessage(socket, message, setClientId) {
108
+ (0, attach_server_clients_1.handleClientMessage)(this, socket, message, setClientId);
476
109
  }
477
-
478
- this.emit('exit', { exitCode, signal });
479
-
480
- // Clean up after short delay (allow clients to receive exit message)
481
- setTimeout(() => {
482
- this._cleanup();
483
- }, 500);
484
- }
485
-
486
- /**
487
- * Handle server error
488
- * @private
489
- */
490
- _onServerError(err) {
491
- this.emit('error', err);
492
- }
493
-
494
- /**
495
- * Clean up resources
496
- * @private
497
- */
498
- async _cleanup() {
499
- // Close all client connections
500
- for (const [, client] of this.clients) {
501
- try {
502
- client.socket.destroy();
503
- } catch {
504
- // Ignore
505
- }
110
+ _removeClient(clientId) {
111
+ (0, attach_server_clients_1.removeClient)(this, clientId);
506
112
  }
507
- this.clients.clear();
508
-
509
- // Close server
510
- if (this.server) {
511
- await new Promise((resolve) => {
512
- this.server.close(() => resolve());
513
- });
514
- this.server = null;
113
+ _sendError(socket, message) {
114
+ (0, attach_server_clients_1.sendClientError)(socket, message);
515
115
  }
516
-
517
- // Remove socket file
518
- if (fs.existsSync(this.socketPath)) {
519
- try {
520
- fs.unlinkSync(this.socketPath);
521
- } catch {
522
- // Ignore
523
- }
116
+ _onProcessExit(exitCode, signal) {
117
+ (0, attach_server_events_1.handleProcessExit)(this, exitCode, signal);
524
118
  }
525
-
526
- // Clean up empty parent directory for cluster sockets
527
- const socketDir = path.dirname(this.socketPath);
528
- if (socketDir.includes('cluster-')) {
529
- try {
530
- const files = fs.readdirSync(socketDir);
531
- if (files.length === 0) {
532
- fs.rmdirSync(socketDir);
533
- }
534
- } catch {
535
- // Ignore
536
- }
119
+ _onServerError(error) {
120
+ this.emit('error', error);
121
+ }
122
+ async _cleanup() {
123
+ await (0, attach_server_cleanup_1.cleanupAttachServer)(this);
537
124
  }
538
-
539
- this.emit('cleanup');
540
- }
541
125
  }
542
-
543
126
  module.exports = AttachServer;