@the-open-engine/zeroshot 6.38.1 → 6.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (377) hide show
  1. package/cli/event-copy.js +8 -7
  2. package/cli/event-copy.ts +12 -0
  3. package/cli/index.js +7 -31
  4. package/cli/json-export.js +61 -64
  5. package/cli/json-export.ts +112 -0
  6. package/cli/message-formatter-utils.js +68 -56
  7. package/cli/message-formatter-utils.ts +121 -0
  8. package/cli/message-formatters-normal.js +124 -259
  9. package/cli/message-formatters-normal.ts +250 -0
  10. package/cli/message-formatters-watch.js +81 -84
  11. package/cli/message-formatters-watch.ts +189 -0
  12. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  13. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  14. package/lib/cluster/generated/protocol.d.cts +8 -0
  15. package/lib/cluster/generated/protocol.d.mts +8 -0
  16. package/lib/cluster/generated/protocol.d.ts +8 -0
  17. package/lib/clusters-registry.d.ts +23 -0
  18. package/lib/clusters-registry.js +17 -29
  19. package/lib/completion.d.ts +12 -0
  20. package/lib/completion.js +84 -94
  21. package/lib/compose-utils.d.ts +32 -0
  22. package/lib/compose-utils.js +57 -72
  23. package/lib/detached-startup.d.ts +83 -0
  24. package/lib/detached-startup.js +231 -302
  25. package/lib/docker-config.d.ts +43 -0
  26. package/lib/docker-config.js +150 -325
  27. package/lib/docker-env-auth.d.ts +17 -0
  28. package/lib/docker-env-auth.js +75 -0
  29. package/lib/git-remote-utils.d.ts +48 -0
  30. package/lib/git-remote-utils.js +147 -213
  31. package/lib/id-detector.d.ts +15 -0
  32. package/lib/id-detector.js +37 -41
  33. package/lib/path-check.d.ts +30 -0
  34. package/lib/path-check.js +42 -45
  35. package/lib/process-liveness.d.ts +16 -0
  36. package/lib/process-liveness.js +19 -12
  37. package/lib/provider-credential-path.d.ts +16 -0
  38. package/lib/provider-credential-path.js +31 -29
  39. package/lib/provider-defaults.d.ts +30 -0
  40. package/lib/provider-defaults.js +47 -42
  41. package/lib/provider-detection.d.ts +11 -0
  42. package/lib/provider-detection.js +91 -54
  43. package/lib/provider-names.d.ts +38 -0
  44. package/lib/provider-names.js +56 -64
  45. package/lib/repo-settings.d.ts +28 -0
  46. package/lib/repo-settings.js +83 -59
  47. package/lib/run-mode.d.ts +21 -0
  48. package/lib/run-mode.js +21 -20
  49. package/lib/run-plan.d.ts +28 -0
  50. package/lib/run-plan.js +17 -16
  51. package/lib/settings/claude-auth.d.ts +35 -0
  52. package/lib/settings/claude-auth.js +30 -47
  53. package/lib/settings-defaults.d.ts +20 -0
  54. package/lib/settings-defaults.js +149 -0
  55. package/lib/settings-error.d.ts +7 -0
  56. package/lib/settings-error.js +8 -0
  57. package/lib/settings-issue-providers.d.ts +10 -0
  58. package/lib/settings-issue-providers.js +12 -0
  59. package/lib/settings-models.d.ts +22 -0
  60. package/lib/settings-models.js +93 -0
  61. package/lib/settings-storage.d.ts +23 -0
  62. package/lib/settings-storage.js +205 -0
  63. package/lib/settings-validation.d.ts +7 -0
  64. package/lib/settings-validation.js +182 -0
  65. package/lib/settings.d.ts +29 -0
  66. package/lib/settings.js +41 -736
  67. package/lib/setup-apply-types.d.ts +66 -0
  68. package/lib/setup-apply-types.js +2 -0
  69. package/lib/setup-apply.d.ts +39 -0
  70. package/lib/setup-apply.js +267 -264
  71. package/lib/setup-journal.d.ts +41 -0
  72. package/lib/setup-journal.js +119 -76
  73. package/lib/setup-plan-types.d.ts +102 -0
  74. package/lib/setup-plan-types.js +2 -0
  75. package/lib/setup-plan.d.ts +30 -0
  76. package/lib/setup-plan.js +300 -324
  77. package/lib/setup-undo.d.ts +44 -0
  78. package/lib/setup-undo.js +61 -74
  79. package/lib/start-cluster-config.d.ts +26 -0
  80. package/lib/start-cluster-config.js +56 -0
  81. package/lib/start-cluster-environment.d.ts +40 -0
  82. package/lib/start-cluster-environment.js +134 -0
  83. package/lib/start-cluster-run-options.d.ts +53 -0
  84. package/lib/start-cluster-run-options.js +147 -0
  85. package/lib/start-cluster.d.ts +64 -0
  86. package/lib/start-cluster.js +98 -454
  87. package/lib/stream-json-parser.d.ts +17 -0
  88. package/lib/stream-json-parser.js +51 -52
  89. package/npm-shrinkwrap.json +2 -2
  90. package/package.json +12 -6
  91. package/scripts/postinstall.js +27 -0
  92. package/scripts/rust-distribution.js +23 -14
  93. package/src/agent/agent-command-proofs-context.js +35 -45
  94. package/src/agent/agent-command-proofs-context.ts +87 -0
  95. package/src/agent/agent-config-settings.js +19 -0
  96. package/src/agent/agent-config-settings.ts +41 -0
  97. package/src/agent/agent-config.js +122 -231
  98. package/src/agent/agent-config.ts +285 -0
  99. package/src/agent/agent-context-builder.js +38 -273
  100. package/src/agent/agent-context-builder.ts +51 -0
  101. package/src/agent/agent-context-environment-sections.js +105 -0
  102. package/src/agent/agent-context-environment-sections.ts +134 -0
  103. package/src/agent/agent-context-packs.js +165 -0
  104. package/src/agent/agent-context-packs.ts +296 -0
  105. package/src/agent/agent-context-prompt-sections.js +100 -0
  106. package/src/agent/agent-context-prompt-sections.ts +148 -0
  107. package/src/agent/agent-context-sections.js +25 -334
  108. package/src/agent/agent-context-sections.ts +36 -0
  109. package/src/agent/agent-context-sources.js +96 -149
  110. package/src/agent/agent-context-sources.ts +253 -0
  111. package/src/agent/agent-context-types.js +2 -0
  112. package/src/agent/agent-context-types.ts +132 -0
  113. package/src/agent/agent-context-validation-sections.js +73 -0
  114. package/src/agent/agent-context-validation-sections.ts +129 -0
  115. package/src/agent/agent-input-injector.js +99 -118
  116. package/src/agent/agent-input-injector.ts +195 -0
  117. package/src/agent/agent-liveness-poll.js +74 -78
  118. package/src/agent/agent-liveness-poll.ts +163 -0
  119. package/src/agent/agent-quality-gate-schema.js +77 -86
  120. package/src/agent/agent-quality-gate-schema.ts +135 -0
  121. package/src/agent/agent-quality-gates-context.js +44 -50
  122. package/src/agent/agent-quality-gates-context.ts +91 -0
  123. package/src/agent/agent-stuck-detector.js +171 -239
  124. package/src/agent/agent-stuck-detector.ts +288 -0
  125. package/src/agent/agent-trigger-evaluator.js +29 -46
  126. package/src/agent/agent-trigger-evaluator.ts +98 -0
  127. package/src/agent/context-metrics.js +110 -141
  128. package/src/agent/context-metrics.ts +261 -0
  129. package/src/agent/context-pack-builder.js +72 -358
  130. package/src/agent/context-pack-builder.ts +105 -0
  131. package/src/agent/context-pack-core.js +70 -0
  132. package/src/agent/context-pack-core.ts +96 -0
  133. package/src/agent/context-pack-selection.js +119 -0
  134. package/src/agent/context-pack-selection.ts +187 -0
  135. package/src/agent/context-pack-truncation.js +139 -0
  136. package/src/agent/context-pack-truncation.ts +208 -0
  137. package/src/agent/context-pack-types.js +2 -0
  138. package/src/agent/context-pack-types.ts +98 -0
  139. package/src/agent/context-replay-policy.js +30 -39
  140. package/src/agent/context-replay-policy.ts +71 -0
  141. package/src/agent/critical-agent-policy.js +6 -10
  142. package/src/agent/critical-agent-policy.ts +20 -0
  143. package/src/agent/guidance-queue.js +74 -87
  144. package/src/agent/guidance-queue.ts +166 -0
  145. package/src/agent/output-extraction-error-detail.js +45 -0
  146. package/src/agent/output-extraction-error-detail.ts +49 -0
  147. package/src/agent/output-extraction-failures.js +125 -0
  148. package/src/agent/output-extraction-failures.ts +149 -0
  149. package/src/agent/output-extraction-json.js +234 -0
  150. package/src/agent/output-extraction-json.ts +235 -0
  151. package/src/agent/output-extraction-pi.js +124 -0
  152. package/src/agent/output-extraction-pi.ts +137 -0
  153. package/src/agent/output-extraction-types.js +2 -0
  154. package/src/agent/output-extraction-types.ts +49 -0
  155. package/src/agent/output-extraction.js +17 -617
  156. package/src/agent/output-extraction.ts +30 -0
  157. package/src/agent/output-reformatter-errors.js +83 -0
  158. package/src/agent/output-reformatter-errors.ts +106 -0
  159. package/src/agent/output-reformatter-types.js +2 -0
  160. package/src/agent/output-reformatter-types.ts +86 -0
  161. package/src/agent/output-reformatter.js +140 -185
  162. package/src/agent/output-reformatter.ts +238 -0
  163. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  164. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  165. package/src/agent/pi-terminal-lifecycle.js +186 -206
  166. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  167. package/src/agent/provider-control-plane.js +22 -21
  168. package/src/agent/provider-control-plane.ts +52 -0
  169. package/src/agent/provider-terminal-failure-types.js +2 -0
  170. package/src/agent/provider-terminal-failure-types.ts +60 -0
  171. package/src/agent/provider-terminal-failure.js +194 -191
  172. package/src/agent/provider-terminal-failure.ts +262 -0
  173. package/src/agent/rate-limit-backoff.js +31 -74
  174. package/src/agent/rate-limit-backoff.ts +71 -0
  175. package/src/agent/schema-utils.js +85 -125
  176. package/src/agent/schema-utils.ts +148 -0
  177. package/src/agent/structured-output-error.js +34 -33
  178. package/src/agent/structured-output-error.ts +105 -0
  179. package/src/agent/validation-platform.js +27 -27
  180. package/src/agent/validation-platform.ts +49 -0
  181. package/src/attach/attach-client.js +232 -405
  182. package/src/attach/attach-client.ts +300 -0
  183. package/src/attach/attach-server-cleanup.js +43 -0
  184. package/src/attach/attach-server-cleanup.ts +39 -0
  185. package/src/attach/attach-server-clients.js +117 -0
  186. package/src/attach/attach-server-clients.ts +122 -0
  187. package/src/attach/attach-server-events.js +38 -0
  188. package/src/attach/attach-server-events.ts +36 -0
  189. package/src/attach/attach-server-pty.js +45 -0
  190. package/src/attach/attach-server-pty.ts +64 -0
  191. package/src/attach/attach-server-runtime.js +73 -0
  192. package/src/attach/attach-server-runtime.ts +62 -0
  193. package/src/attach/attach-server-socket.js +28 -0
  194. package/src/attach/attach-server-socket.ts +23 -0
  195. package/src/attach/attach-server-types.js +2 -0
  196. package/src/attach/attach-server-types.ts +82 -0
  197. package/src/attach/attach-server.js +106 -523
  198. package/src/attach/attach-server.ts +158 -0
  199. package/src/attach/index.js +18 -35
  200. package/src/attach/index.ts +18 -0
  201. package/src/attach/protocol.js +95 -184
  202. package/src/attach/protocol.ts +181 -0
  203. package/src/attach/ring-buffer.js +76 -102
  204. package/src/attach/ring-buffer.ts +109 -0
  205. package/src/attach/send-input.js +64 -75
  206. package/src/attach/send-input.ts +94 -0
  207. package/src/attach/socket-discovery.js +164 -218
  208. package/src/attach/socket-discovery.ts +230 -0
  209. package/src/attach/socket-paths.js +42 -61
  210. package/src/attach/socket-paths.ts +81 -0
  211. package/src/claude-credentials.js +51 -54
  212. package/src/claude-credentials.ts +89 -0
  213. package/src/cluster/generated/protocol-schema.ts +1 -1
  214. package/src/cluster/generated/protocol.ts +2 -1
  215. package/src/command-proofs.js +110 -141
  216. package/src/command-proofs.ts +216 -0
  217. package/src/config-router.js +81 -73
  218. package/src/config-router.ts +131 -0
  219. package/src/copy-worker.js +53 -29
  220. package/src/copy-worker.ts +75 -0
  221. package/src/darwin-keychain-boundary.js +80 -111
  222. package/src/darwin-keychain-boundary.ts +148 -0
  223. package/src/guidance-topics.js +4 -5
  224. package/src/guidance-topics.ts +10 -0
  225. package/src/input-helpers.js +33 -54
  226. package/src/input-helpers.ts +58 -0
  227. package/src/ledger-sequence.js +45 -48
  228. package/src/ledger-sequence.ts +63 -0
  229. package/src/legacy-lib/clusters-registry.ts +40 -0
  230. package/src/legacy-lib/completion.ts +148 -0
  231. package/src/legacy-lib/compose-utils.ts +102 -0
  232. package/src/legacy-lib/detached-startup.ts +449 -0
  233. package/src/legacy-lib/docker-config.ts +282 -0
  234. package/src/legacy-lib/docker-env-auth.ts +116 -0
  235. package/src/legacy-lib/git-remote-utils.ts +244 -0
  236. package/src/legacy-lib/id-detector.ts +57 -0
  237. package/src/legacy-lib/js-yaml.d.ts +3 -0
  238. package/src/legacy-lib/omelette.d.ts +15 -0
  239. package/src/legacy-lib/path-check.ts +89 -0
  240. package/src/legacy-lib/process-liveness.ts +36 -0
  241. package/src/legacy-lib/provider-credential-path.ts +57 -0
  242. package/src/legacy-lib/provider-defaults.ts +114 -0
  243. package/src/legacy-lib/provider-detection.ts +67 -0
  244. package/src/legacy-lib/provider-names.ts +126 -0
  245. package/src/legacy-lib/repo-settings.ts +88 -0
  246. package/src/legacy-lib/run-mode.ts +58 -0
  247. package/src/legacy-lib/run-plan.ts +49 -0
  248. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  249. package/src/legacy-lib/settings-defaults.ts +212 -0
  250. package/src/legacy-lib/settings-error.ts +8 -0
  251. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  252. package/src/legacy-lib/settings-models.ts +124 -0
  253. package/src/legacy-lib/settings-storage.ts +277 -0
  254. package/src/legacy-lib/settings-validation.ts +220 -0
  255. package/src/legacy-lib/settings.ts +87 -0
  256. package/src/legacy-lib/setup-apply-types.ts +70 -0
  257. package/src/legacy-lib/setup-apply.ts +456 -0
  258. package/src/legacy-lib/setup-journal.ts +185 -0
  259. package/src/legacy-lib/setup-plan-types.ts +96 -0
  260. package/src/legacy-lib/setup-plan.ts +500 -0
  261. package/src/legacy-lib/setup-undo.ts +142 -0
  262. package/src/legacy-lib/start-cluster-config.ts +124 -0
  263. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  264. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  265. package/src/legacy-lib/start-cluster.ts +237 -0
  266. package/src/legacy-lib/stream-json-parser.ts +88 -0
  267. package/src/message-buffer.js +55 -71
  268. package/src/message-buffer.ts +107 -0
  269. package/src/message-bus-bridge.js +92 -133
  270. package/src/message-bus-bridge.ts +149 -0
  271. package/src/name-generator-shared.js +220 -0
  272. package/src/name-generator-shared.ts +231 -0
  273. package/src/name-generator.js +8 -217
  274. package/src/name-generator.ts +27 -0
  275. package/src/omp-blob-root.js +83 -64
  276. package/src/omp-blob-root.ts +116 -0
  277. package/src/omp-config-overlay.js +65 -38
  278. package/src/omp-config-overlay.ts +110 -0
  279. package/src/omp-execution-fingerprint.js +38 -43
  280. package/src/omp-execution-fingerprint.ts +92 -0
  281. package/src/omp-session-limits.js +10 -15
  282. package/src/omp-session-limits.ts +53 -0
  283. package/src/omp-session-partition.js +2 -2
  284. package/src/omp-session-verifier.js +1 -1
  285. package/src/orchestrator.js +19 -4
  286. package/src/providers/anthropic/index.js +3 -1
  287. package/src/providers/anthropic/index.ts +13 -0
  288. package/src/providers/capabilities.js +19 -27
  289. package/src/providers/capabilities.ts +44 -0
  290. package/src/providers/google/index.js +3 -1
  291. package/src/providers/google/index.ts +13 -0
  292. package/src/providers/openai/index.js +3 -1
  293. package/src/providers/openai/index.ts +13 -0
  294. package/src/providers/opencode/index.js +3 -1
  295. package/src/providers/opencode/index.ts +13 -0
  296. package/src/quality-gates.js +67 -127
  297. package/src/quality-gates.ts +149 -0
  298. package/src/repo-settings-access.js +40 -0
  299. package/src/repo-settings-access.ts +64 -0
  300. package/src/schemas/sub-cluster.js +127 -183
  301. package/src/schemas/sub-cluster.ts +238 -0
  302. package/src/state-snapshot-normalization.js +224 -0
  303. package/src/state-snapshot-normalization.ts +222 -0
  304. package/src/state-snapshot.js +192 -359
  305. package/src/state-snapshot.ts +291 -0
  306. package/src/state-snapshotter.js +118 -130
  307. package/src/state-snapshotter.ts +167 -0
  308. package/src/sub-cluster-wrapper.js +4 -13
  309. package/src/task-run-model-args.js +87 -124
  310. package/src/task-run-model-args.ts +204 -0
  311. package/src/task-runner.js +5 -25
  312. package/src/task-runner.ts +28 -0
  313. package/src/task-startup-error.js +73 -58
  314. package/src/task-startup-error.ts +126 -0
  315. package/src/template-validation/consensus-gate-contracts.js +2 -0
  316. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  317. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  318. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  319. package/src/template-validation/consensus-gate-stage.js +34 -0
  320. package/src/template-validation/consensus-gate-stage.ts +56 -0
  321. package/src/template-validation/random-topology-contracts.js +2 -0
  322. package/src/template-validation/random-topology-contracts.ts +54 -0
  323. package/src/template-validation/random-topology-dispatch.js +25 -0
  324. package/src/template-validation/random-topology-dispatch.ts +33 -0
  325. package/src/template-validation/random-topology-message-loop.js +53 -0
  326. package/src/template-validation/random-topology-message-loop.ts +73 -0
  327. package/src/template-validation/random-topology-operations.js +79 -0
  328. package/src/template-validation/random-topology-operations.ts +101 -0
  329. package/src/template-validation/random-topology-runtime.js +25 -0
  330. package/src/template-validation/random-topology-runtime.ts +43 -0
  331. package/src/template-validation/random-topology-scenario.js +52 -0
  332. package/src/template-validation/random-topology-scenario.ts +57 -0
  333. package/src/template-validation/random-topology-schema.js +159 -0
  334. package/src/template-validation/random-topology-schema.ts +190 -0
  335. package/src/template-validation/random-topology-state.js +28 -0
  336. package/src/template-validation/random-topology-state.ts +30 -0
  337. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  338. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  339. package/src/template-validation/random-topology-trigger.js +75 -0
  340. package/src/template-validation/random-topology-trigger.ts +88 -0
  341. package/src/template-validation/report-formatter.js +40 -46
  342. package/src/template-validation/report-formatter.ts +101 -0
  343. package/src/template-validation/simulate-consensus-gates.js +111 -302
  344. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  345. package/src/template-validation/simulate-random-topology.js +26 -519
  346. package/src/template-validation/simulate-random-topology.ts +57 -0
  347. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  348. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  349. package/src/template-validation/simulation-agent-runtime.js +25 -0
  350. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  351. package/src/template-validation/simulation-agent.js +29 -0
  352. package/src/template-validation/simulation-agent.ts +73 -0
  353. package/src/template-validation/simulation-runtime.js +34 -0
  354. package/src/template-validation/simulation-runtime.ts +72 -0
  355. package/src/template-validation/two-stage-contracts.js +2 -0
  356. package/src/template-validation/two-stage-contracts.ts +41 -0
  357. package/src/template-validation/two-stage-inputs.js +21 -0
  358. package/src/template-validation/two-stage-inputs.ts +29 -0
  359. package/src/template-validation/two-stage-results.js +30 -0
  360. package/src/template-validation/two-stage-results.ts +40 -0
  361. package/src/template-validation/two-stage-scenario.js +86 -0
  362. package/src/template-validation/two-stage-scenario.ts +120 -0
  363. package/src/worktree-claude-config.js +182 -220
  364. package/src/worktree-claude-config.ts +272 -0
  365. package/src/worktree-tooling-env.js +103 -125
  366. package/src/worktree-tooling-env.ts +142 -0
  367. package/task-lib/completion.js +2 -3
  368. package/task-lib/completion.ts +9 -0
  369. package/task-lib/config.js +1 -4
  370. package/task-lib/config.ts +11 -0
  371. package/task-lib/name-generator.js +4 -226
  372. package/task-lib/name-generator.ts +11 -0
  373. package/task-lib/omp-session-cleanup.js +1 -1
  374. package/task-lib/omp-storage-root.js +8 -12
  375. package/task-lib/omp-storage-root.ts +62 -0
  376. package/task-lib/process-termination.js +143 -166
  377. package/task-lib/process-termination.ts +268 -0
@@ -0,0 +1,181 @@
1
+ /**
2
+ * Protocol - Message framing for attach/detach IPC
3
+ *
4
+ * Uses length-prefixed JSON messages over Unix sockets.
5
+ * Format: [4-byte length (BE)] [JSON payload]
6
+ */
7
+
8
+ const MAX_MESSAGE_SIZE = 10 * 1024 * 1024; // 10MB max message
9
+
10
+ const MessageType = {
11
+ // Client → Server
12
+ ATTACH: 'attach',
13
+ DETACH: 'detach',
14
+ RESIZE: 'resize',
15
+ SIGNAL: 'signal',
16
+ STDIN: 'stdin',
17
+
18
+ // Server → Client
19
+ OUTPUT: 'output',
20
+ HISTORY: 'history',
21
+ STATE: 'state',
22
+ EXIT: 'exit',
23
+ ERROR: 'error',
24
+ } as const;
25
+
26
+ type BinaryData = Buffer | string;
27
+ type MessageWithData = { data?: string | null };
28
+ type AttachMessage = {
29
+ type: typeof MessageType.ATTACH;
30
+ clientId: string;
31
+ cols: number;
32
+ rows: number;
33
+ };
34
+ type DetachMessage = { type: typeof MessageType.DETACH; clientId: string };
35
+ type ResizeMessage = { type: typeof MessageType.RESIZE; cols: number; rows: number };
36
+ type SignalMessage = { type: typeof MessageType.SIGNAL; signal: string };
37
+ type DataMessage<T extends string> = { type: T; data: string };
38
+ type OutputMessage = DataMessage<typeof MessageType.OUTPUT> & { timestamp: number };
39
+ type ExitMessage = {
40
+ type: typeof MessageType.EXIT;
41
+ code: number | null;
42
+ signal: string | number | undefined | null;
43
+ };
44
+ type ErrorMessage = { type: typeof MessageType.ERROR; message: string };
45
+
46
+ /** Encode a message for transmission. */
47
+ function encode(message: object): Buffer {
48
+ const json = JSON.stringify(message) as string;
49
+ const payload = Buffer.from(json, 'utf8');
50
+
51
+ if (payload.length > MAX_MESSAGE_SIZE) {
52
+ throw new Error(`Message too large: ${payload.length} bytes (max ${MAX_MESSAGE_SIZE})`);
53
+ }
54
+
55
+ const frame = Buffer.alloc(4 + payload.length);
56
+ frame.writeUInt32BE(payload.length, 0);
57
+ payload.copy(frame, 4);
58
+
59
+ return frame;
60
+ }
61
+
62
+ /** Streaming decoder for framed messages. */
63
+ class MessageDecoder {
64
+ buffer: Buffer;
65
+
66
+ constructor() {
67
+ this.buffer = Buffer.alloc(0);
68
+ }
69
+
70
+ /** Feed a received data chunk into the decoder. */
71
+ feed(data: Buffer): unknown[] {
72
+ this.buffer = Buffer.concat([this.buffer, data]);
73
+ const messages: unknown[] = [];
74
+
75
+ while (this.buffer.length >= 4) {
76
+ const length = this.buffer.readUInt32BE(0);
77
+
78
+ if (length > MAX_MESSAGE_SIZE) {
79
+ throw new Error(`Message too large: ${length} bytes (max ${MAX_MESSAGE_SIZE})`);
80
+ }
81
+
82
+ if (this.buffer.length < 4 + length) {
83
+ // Incomplete message, wait for more data
84
+ break;
85
+ }
86
+
87
+ const payload = this.buffer.slice(4, 4 + length);
88
+ this.buffer = this.buffer.slice(4 + length);
89
+
90
+ try {
91
+ const message: unknown = JSON.parse(payload.toString('utf8'));
92
+ messages.push(message);
93
+ } catch (error: unknown) {
94
+ const reason = error instanceof Error ? error.message : String(error);
95
+ throw new Error(`Invalid JSON in message: ${reason}`);
96
+ }
97
+ }
98
+
99
+ return messages;
100
+ }
101
+
102
+ /** Reset decoder state. */
103
+ reset(): void {
104
+ this.buffer = Buffer.alloc(0);
105
+ }
106
+ }
107
+
108
+ function createAttachMessage(clientId: string, cols: number, rows: number): AttachMessage {
109
+ return { type: MessageType.ATTACH, clientId, cols, rows };
110
+ }
111
+
112
+ function createDetachMessage(clientId: string): DetachMessage {
113
+ return { type: MessageType.DETACH, clientId };
114
+ }
115
+
116
+ function createResizeMessage(cols: number, rows: number): ResizeMessage {
117
+ return { type: MessageType.RESIZE, cols, rows };
118
+ }
119
+
120
+ function createSignalMessage(signal: string): SignalMessage {
121
+ if (!['SIGINT', 'SIGTERM', 'SIGKILL', 'SIGTSTP'].includes(signal)) {
122
+ throw new Error(`Invalid signal: ${signal}`);
123
+ }
124
+ return { type: MessageType.SIGNAL, signal };
125
+ }
126
+
127
+ function createStdinMessage(data: BinaryData): DataMessage<typeof MessageType.STDIN> {
128
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
129
+ return { type: MessageType.STDIN, data: buf.toString('base64') };
130
+ }
131
+
132
+ function createOutputMessage(data: BinaryData, timestamp = Date.now()): OutputMessage {
133
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
134
+ return { type: MessageType.OUTPUT, data: buf.toString('base64'), timestamp };
135
+ }
136
+
137
+ function createHistoryMessage(data: BinaryData): DataMessage<typeof MessageType.HISTORY> {
138
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
139
+ return { type: MessageType.HISTORY, data: buf.toString('base64') };
140
+ }
141
+
142
+ function createStateMessage(state: Record<string, unknown>): Record<string, unknown> {
143
+ return { type: MessageType.STATE, ...state };
144
+ }
145
+
146
+ function createExitMessage(
147
+ code: number | null,
148
+ signal: string | number | undefined | null
149
+ ): ExitMessage {
150
+ return { type: MessageType.EXIT, code, signal };
151
+ }
152
+
153
+ function createErrorMessage(message: string): ErrorMessage {
154
+ return { type: MessageType.ERROR, message };
155
+ }
156
+
157
+ /** Decode the base64 data field from OUTPUT/HISTORY/STDIN messages. */
158
+ function decodeData(message: MessageWithData): Buffer | null {
159
+ if (message.data) {
160
+ return Buffer.from(message.data, 'base64');
161
+ }
162
+ return null;
163
+ }
164
+
165
+ export = {
166
+ encode,
167
+ MessageDecoder,
168
+ MessageType,
169
+ createAttachMessage,
170
+ createDetachMessage,
171
+ createResizeMessage,
172
+ createSignalMessage,
173
+ createStdinMessage,
174
+ createOutputMessage,
175
+ createHistoryMessage,
176
+ createStateMessage,
177
+ createExitMessage,
178
+ createErrorMessage,
179
+ decodeData,
180
+ MAX_MESSAGE_SIZE,
181
+ };
@@ -1,3 +1,4 @@
1
+ "use strict";
1
2
  /**
2
3
  * RingBuffer - Fixed-size circular buffer for output history
3
4
  *
@@ -9,113 +10,86 @@
9
10
  * - O(1) write and read operations
10
11
  * - Thread-safe for single writer (Node.js is single-threaded)
11
12
  */
12
-
13
13
  class RingBuffer {
14
- /**
15
- * @param {number} maxSize - Maximum buffer size in bytes (default 1MB)
16
- */
17
- constructor(maxSize = 1024 * 1024) {
18
- if (maxSize <= 0) {
19
- throw new Error('RingBuffer maxSize must be positive');
14
+ buffer;
15
+ maxSize;
16
+ writePos;
17
+ size;
18
+ /**
19
+ * @param maxSize - Maximum buffer size in bytes (default 1MB)
20
+ */
21
+ constructor(maxSize = 1024 * 1024) {
22
+ if (maxSize <= 0) {
23
+ throw new Error('RingBuffer maxSize must be positive');
24
+ }
25
+ this.buffer = Buffer.alloc(maxSize);
26
+ this.maxSize = maxSize;
27
+ this.writePos = 0; // Next write position
28
+ this.size = 0; // Current data size (0 to maxSize)
20
29
  }
21
- this.buffer = Buffer.alloc(maxSize);
22
- this.maxSize = maxSize;
23
- this.writePos = 0; // Next write position
24
- this.size = 0; // Current data size (0 to maxSize)
25
- }
26
-
27
- /**
28
- * Write data to the buffer
29
- * @param {Buffer|string} data - Data to write
30
- */
31
- write(data) {
32
- const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
33
-
34
- if (buf.length === 0) return;
35
-
36
- // If data is larger than buffer, only keep the last maxSize bytes
37
- if (buf.length >= this.maxSize) {
38
- buf.copy(this.buffer, 0, buf.length - this.maxSize);
39
- this.writePos = 0;
40
- this.size = this.maxSize;
41
- return;
30
+ /** Write data to the buffer. */
31
+ write(data) {
32
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
33
+ if (buf.length === 0)
34
+ return;
35
+ // If data is larger than buffer, only keep the last maxSize bytes
36
+ if (buf.length >= this.maxSize) {
37
+ buf.copy(this.buffer, 0, buf.length - this.maxSize);
38
+ this.writePos = 0;
39
+ this.size = this.maxSize;
40
+ return;
41
+ }
42
+ // Calculate how much wraps around
43
+ const spaceToEnd = this.maxSize - this.writePos;
44
+ if (buf.length <= spaceToEnd) {
45
+ // No wrap needed
46
+ buf.copy(this.buffer, this.writePos);
47
+ this.writePos += buf.length;
48
+ }
49
+ else {
50
+ // Wrap around
51
+ buf.copy(this.buffer, this.writePos, 0, spaceToEnd);
52
+ buf.copy(this.buffer, 0, spaceToEnd);
53
+ this.writePos = buf.length - spaceToEnd;
54
+ }
55
+ // Update size (capped at maxSize)
56
+ this.size = Math.min(this.size + buf.length, this.maxSize);
42
57
  }
43
-
44
- // Calculate how much wraps around
45
- const spaceToEnd = this.maxSize - this.writePos;
46
-
47
- if (buf.length <= spaceToEnd) {
48
- // No wrap needed
49
- buf.copy(this.buffer, this.writePos);
50
- this.writePos += buf.length;
51
- } else {
52
- // Wrap around
53
- buf.copy(this.buffer, this.writePos, 0, spaceToEnd);
54
- buf.copy(this.buffer, 0, spaceToEnd);
55
- this.writePos = buf.length - spaceToEnd;
58
+ /** Read all buffered data. */
59
+ read() {
60
+ if (this.size === 0) {
61
+ return Buffer.alloc(0);
62
+ }
63
+ const result = Buffer.alloc(this.size);
64
+ if (this.size < this.maxSize) {
65
+ // Buffer not full yet, data starts at 0
66
+ this.buffer.copy(result, 0, 0, this.size);
67
+ }
68
+ else {
69
+ // Buffer is full, data starts at writePos (oldest data)
70
+ const startPos = this.writePos;
71
+ const firstChunkSize = this.maxSize - startPos;
72
+ this.buffer.copy(result, 0, startPos, this.maxSize);
73
+ this.buffer.copy(result, firstChunkSize, 0, startPos);
74
+ }
75
+ return result;
56
76
  }
57
-
58
- // Update size (capped at maxSize)
59
- this.size = Math.min(this.size + buf.length, this.maxSize);
60
- }
61
-
62
- /**
63
- * Read all buffered data
64
- * @returns {Buffer} - All data currently in buffer
65
- */
66
- read() {
67
- if (this.size === 0) {
68
- return Buffer.alloc(0);
77
+ /** Clear the buffer. */
78
+ clear() {
79
+ this.writePos = 0;
80
+ this.size = 0;
69
81
  }
70
-
71
- const result = Buffer.alloc(this.size);
72
-
73
- if (this.size < this.maxSize) {
74
- // Buffer not full yet, data starts at 0
75
- this.buffer.copy(result, 0, 0, this.size);
76
- } else {
77
- // Buffer is full, data starts at writePos (oldest data)
78
- const startPos = this.writePos;
79
- const firstChunkSize = this.maxSize - startPos;
80
-
81
- this.buffer.copy(result, 0, startPos, this.maxSize);
82
- this.buffer.copy(result, firstChunkSize, 0, startPos);
82
+ /** Get current data size. */
83
+ getSize() {
84
+ return this.size;
85
+ }
86
+ /** Check if buffer is empty. */
87
+ isEmpty() {
88
+ return this.size === 0;
89
+ }
90
+ /** Check if buffer is full. */
91
+ isFull() {
92
+ return this.size === this.maxSize;
83
93
  }
84
-
85
- return result;
86
- }
87
-
88
- /**
89
- * Clear the buffer
90
- */
91
- clear() {
92
- this.writePos = 0;
93
- this.size = 0;
94
- }
95
-
96
- /**
97
- * Get current data size
98
- * @returns {number}
99
- */
100
- getSize() {
101
- return this.size;
102
- }
103
-
104
- /**
105
- * Check if buffer is empty
106
- * @returns {boolean}
107
- */
108
- isEmpty() {
109
- return this.size === 0;
110
- }
111
-
112
- /**
113
- * Check if buffer is full
114
- * @returns {boolean}
115
- */
116
- isFull() {
117
- return this.size === this.maxSize;
118
- }
119
94
  }
120
-
121
95
  module.exports = RingBuffer;
@@ -0,0 +1,109 @@
1
+ /**
2
+ * RingBuffer - Fixed-size circular buffer for output history
3
+ *
4
+ * Used by AttachServer to store recent output for late-joining clients.
5
+ * When buffer fills, oldest data is overwritten.
6
+ *
7
+ * Design:
8
+ * - Fixed allocation (no dynamic resizing)
9
+ * - O(1) write and read operations
10
+ * - Thread-safe for single writer (Node.js is single-threaded)
11
+ */
12
+
13
+ class RingBuffer {
14
+ buffer: Buffer;
15
+ maxSize: number;
16
+ writePos: number;
17
+ size: number;
18
+
19
+ /**
20
+ * @param maxSize - Maximum buffer size in bytes (default 1MB)
21
+ */
22
+ constructor(maxSize = 1024 * 1024) {
23
+ if (maxSize <= 0) {
24
+ throw new Error('RingBuffer maxSize must be positive');
25
+ }
26
+ this.buffer = Buffer.alloc(maxSize);
27
+ this.maxSize = maxSize;
28
+ this.writePos = 0; // Next write position
29
+ this.size = 0; // Current data size (0 to maxSize)
30
+ }
31
+
32
+ /** Write data to the buffer. */
33
+ write(data: Buffer | string): void {
34
+ const buf = Buffer.isBuffer(data) ? data : Buffer.from(data);
35
+
36
+ if (buf.length === 0) return;
37
+
38
+ // If data is larger than buffer, only keep the last maxSize bytes
39
+ if (buf.length >= this.maxSize) {
40
+ buf.copy(this.buffer, 0, buf.length - this.maxSize);
41
+ this.writePos = 0;
42
+ this.size = this.maxSize;
43
+ return;
44
+ }
45
+
46
+ // Calculate how much wraps around
47
+ const spaceToEnd = this.maxSize - this.writePos;
48
+
49
+ if (buf.length <= spaceToEnd) {
50
+ // No wrap needed
51
+ buf.copy(this.buffer, this.writePos);
52
+ this.writePos += buf.length;
53
+ } else {
54
+ // Wrap around
55
+ buf.copy(this.buffer, this.writePos, 0, spaceToEnd);
56
+ buf.copy(this.buffer, 0, spaceToEnd);
57
+ this.writePos = buf.length - spaceToEnd;
58
+ }
59
+
60
+ // Update size (capped at maxSize)
61
+ this.size = Math.min(this.size + buf.length, this.maxSize);
62
+ }
63
+
64
+ /** Read all buffered data. */
65
+ read(): Buffer {
66
+ if (this.size === 0) {
67
+ return Buffer.alloc(0);
68
+ }
69
+
70
+ const result = Buffer.alloc(this.size);
71
+
72
+ if (this.size < this.maxSize) {
73
+ // Buffer not full yet, data starts at 0
74
+ this.buffer.copy(result, 0, 0, this.size);
75
+ } else {
76
+ // Buffer is full, data starts at writePos (oldest data)
77
+ const startPos = this.writePos;
78
+ const firstChunkSize = this.maxSize - startPos;
79
+
80
+ this.buffer.copy(result, 0, startPos, this.maxSize);
81
+ this.buffer.copy(result, firstChunkSize, 0, startPos);
82
+ }
83
+
84
+ return result;
85
+ }
86
+
87
+ /** Clear the buffer. */
88
+ clear(): void {
89
+ this.writePos = 0;
90
+ this.size = 0;
91
+ }
92
+
93
+ /** Get current data size. */
94
+ getSize(): number {
95
+ return this.size;
96
+ }
97
+
98
+ /** Check if buffer is empty. */
99
+ isEmpty(): boolean {
100
+ return this.size === 0;
101
+ }
102
+
103
+ /** Check if buffer is full. */
104
+ isFull(): boolean {
105
+ return this.size === this.maxSize;
106
+ }
107
+ }
108
+
109
+ export = RingBuffer;
@@ -1,88 +1,77 @@
1
+ "use strict";
1
2
  /**
2
3
  * sendInput - write stdin data to a live attach socket
3
4
  *
4
5
  * Uses the attach protocol's STDIN message to forward input to the PTY.
5
6
  * Returns { ok, error } instead of throwing on transport failures.
6
7
  */
7
-
8
- const net = require('net');
9
- const fs = require('fs');
10
- const protocol = require('./protocol');
11
-
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ const node_fs_1 = __importDefault(require("node:fs"));
12
+ const node_net_1 = __importDefault(require("node:net"));
13
+ const protocol_1 = __importDefault(require("./protocol"));
12
14
  const DEFAULT_TIMEOUT_MS = 1500;
13
-
14
- /**
15
- * Send input to an attach socket via STDIN message.
16
- * @param {object} options
17
- * @param {string} options.socketPath - Unix socket path
18
- * @param {Buffer|string} options.data - Data to send
19
- * @param {number} [options.timeoutMs=1500] - Timeout in ms
20
- * @returns {Promise<{ok: boolean, error: string|null}>}
21
- */
15
+ /** Send input to an attach socket via STDIN message. */
22
16
  function sendInput(options = {}) {
23
- const { socketPath, data, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
24
-
25
- if (!socketPath) {
26
- throw new Error('sendInput: socketPath is required');
27
- }
28
-
29
- if (data === undefined || data === null) {
30
- throw new Error('sendInput: data is required');
31
- }
32
-
33
- if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
34
- throw new Error(`sendInput: timeoutMs must be positive (got ${timeoutMs})`);
35
- }
36
-
37
- if (!fs.existsSync(socketPath)) {
38
- return { ok: false, error: `Socket not found: ${socketPath}` };
39
- }
40
-
41
- return new Promise((resolve) => {
42
- let settled = false;
43
- let timeout;
44
- const socket = net.createConnection(socketPath);
45
-
46
- const finish = (result) => {
47
- if (settled) return;
48
- settled = true;
49
- if (timeout) {
50
- clearTimeout(timeout);
51
- }
52
- try {
53
- socket.end();
54
- socket.destroy();
55
- } catch (cleanupError) {
56
- console.warn('[sendInput] socket cleanup failed:', cleanupError);
57
- }
58
- resolve(result);
59
- };
60
-
61
- timeout = setTimeout(() => {
62
- finish({ ok: false, error: 'Timeout waiting for socket connection' });
63
- }, timeoutMs);
64
-
65
- socket.on('connect', () => {
66
- try {
67
- const encoded = protocol.encode(protocol.createStdinMessage(data));
68
- socket.write(encoded, (err) => {
69
- if (err) {
70
- finish({ ok: false, error: err.message });
71
- } else {
72
- finish({ ok: true, error: null });
73
- }
17
+ const { socketPath, data, timeoutMs = DEFAULT_TIMEOUT_MS } = options;
18
+ if (!socketPath) {
19
+ throw new Error('sendInput: socketPath is required');
20
+ }
21
+ if (data === undefined || data === null) {
22
+ throw new Error('sendInput: data is required');
23
+ }
24
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
25
+ throw new Error(`sendInput: timeoutMs must be positive (got ${timeoutMs})`);
26
+ }
27
+ if (!node_fs_1.default.existsSync(socketPath)) {
28
+ return { ok: false, error: `Socket not found: ${socketPath}` };
29
+ }
30
+ return new Promise((resolve) => {
31
+ let settled = false;
32
+ let timeout;
33
+ const socket = node_net_1.default.createConnection(socketPath);
34
+ const finish = (result) => {
35
+ if (settled)
36
+ return;
37
+ settled = true;
38
+ if (timeout) {
39
+ clearTimeout(timeout);
40
+ }
41
+ try {
42
+ socket.end();
43
+ socket.destroy();
44
+ }
45
+ catch (cleanupError) {
46
+ console.warn('[sendInput] socket cleanup failed:', cleanupError);
47
+ }
48
+ resolve(result);
49
+ };
50
+ timeout = setTimeout(() => {
51
+ finish({ ok: false, error: 'Timeout waiting for socket connection' });
52
+ }, timeoutMs);
53
+ socket.on('connect', () => {
54
+ try {
55
+ const encoded = protocol_1.default.encode(protocol_1.default.createStdinMessage(data));
56
+ socket.write(encoded, (error) => {
57
+ if (error) {
58
+ finish({ ok: false, error: error.message });
59
+ }
60
+ else {
61
+ finish({ ok: true, error: null });
62
+ }
63
+ });
64
+ }
65
+ catch (error) {
66
+ const reason = error instanceof Error ? error.message : String(error);
67
+ finish({ ok: false, error: reason });
68
+ }
69
+ });
70
+ socket.on('error', (error) => {
71
+ finish({ ok: false, error: error.message });
74
72
  });
75
- } catch (err) {
76
- finish({ ok: false, error: err.message });
77
- }
78
- });
79
-
80
- socket.on('error', (err) => {
81
- finish({ ok: false, error: err.message });
82
73
  });
83
- });
84
74
  }
85
-
86
75
  module.exports = {
87
- sendInput,
76
+ sendInput,
88
77
  };