mstro-app 0.5.1 → 0.5.6

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 (283) hide show
  1. package/PRIVACY.md +9 -9
  2. package/README.md +71 -28
  3. package/bin/commands/config.js +1 -1
  4. package/bin/mstro.js +55 -4
  5. package/dist/server/cli/eta-estimator.d.ts +55 -0
  6. package/dist/server/cli/eta-estimator.d.ts.map +1 -0
  7. package/dist/server/cli/eta-estimator.js +222 -0
  8. package/dist/server/cli/eta-estimator.js.map +1 -0
  9. package/dist/server/cli/headless/claude-invoker-process.d.ts.map +1 -1
  10. package/dist/server/cli/headless/claude-invoker-process.js +9 -1
  11. package/dist/server/cli/headless/claude-invoker-process.js.map +1 -1
  12. package/dist/server/cli/headless/mcp-config.d.ts +22 -5
  13. package/dist/server/cli/headless/mcp-config.d.ts.map +1 -1
  14. package/dist/server/cli/headless/mcp-config.js +7 -5
  15. package/dist/server/cli/headless/mcp-config.js.map +1 -1
  16. package/dist/server/cli/headless/runner.d.ts.map +1 -1
  17. package/dist/server/cli/headless/runner.js +19 -0
  18. package/dist/server/cli/headless/runner.js.map +1 -1
  19. package/dist/server/cli/headless/stall-assessor.d.ts +50 -0
  20. package/dist/server/cli/headless/stall-assessor.d.ts.map +1 -1
  21. package/dist/server/cli/headless/stall-assessor.js +64 -9
  22. package/dist/server/cli/headless/stall-assessor.js.map +1 -1
  23. package/dist/server/cli/headless/tool-watchdog.d.ts +21 -0
  24. package/dist/server/cli/headless/tool-watchdog.d.ts.map +1 -1
  25. package/dist/server/cli/headless/tool-watchdog.js +19 -12
  26. package/dist/server/cli/headless/tool-watchdog.js.map +1 -1
  27. package/dist/server/cli/headless/types.d.ts +16 -1
  28. package/dist/server/cli/headless/types.d.ts.map +1 -1
  29. package/dist/server/cli/improvisation-history-store.d.ts.map +1 -1
  30. package/dist/server/cli/improvisation-history-store.js +5 -1
  31. package/dist/server/cli/improvisation-history-store.js.map +1 -1
  32. package/dist/server/cli/improvisation-output-queue.d.ts +5 -1
  33. package/dist/server/cli/improvisation-output-queue.d.ts.map +1 -1
  34. package/dist/server/cli/improvisation-output-queue.js +30 -7
  35. package/dist/server/cli/improvisation-output-queue.js.map +1 -1
  36. package/dist/server/cli/improvisation-session-manager.d.ts +35 -0
  37. package/dist/server/cli/improvisation-session-manager.d.ts.map +1 -1
  38. package/dist/server/cli/improvisation-session-manager.js +58 -1
  39. package/dist/server/cli/improvisation-session-manager.js.map +1 -1
  40. package/dist/server/cli/improvisation-types.d.ts +9 -0
  41. package/dist/server/cli/improvisation-types.d.ts.map +1 -1
  42. package/dist/server/cli/improvisation-types.js.map +1 -1
  43. package/dist/server/cli/retry/retry-runner-factory.d.ts.map +1 -1
  44. package/dist/server/cli/retry/retry-runner-factory.js +1 -0
  45. package/dist/server/cli/retry/retry-runner-factory.js.map +1 -1
  46. package/dist/server/engines/EngineEvent.d.ts +126 -0
  47. package/dist/server/engines/EngineEvent.d.ts.map +1 -0
  48. package/dist/server/engines/EngineEvent.js +11 -0
  49. package/dist/server/engines/EngineEvent.js.map +1 -0
  50. package/dist/server/engines/claude/ClaudeCodeEngine.d.ts +47 -0
  51. package/dist/server/engines/claude/ClaudeCodeEngine.d.ts.map +1 -0
  52. package/dist/server/engines/claude/ClaudeCodeEngine.js +338 -0
  53. package/dist/server/engines/claude/ClaudeCodeEngine.js.map +1 -0
  54. package/dist/server/engines/factory.d.ts +21 -0
  55. package/dist/server/engines/factory.d.ts.map +1 -0
  56. package/dist/server/engines/factory.js +152 -0
  57. package/dist/server/engines/factory.js.map +1 -0
  58. package/dist/server/engines/opencode/OpenCodeEngine.d.ts +148 -0
  59. package/dist/server/engines/opencode/OpenCodeEngine.d.ts.map +1 -0
  60. package/dist/server/engines/opencode/OpenCodeEngine.js +630 -0
  61. package/dist/server/engines/opencode/OpenCodeEngine.js.map +1 -0
  62. package/dist/server/engines/opencode/OpenCodeServerManager.d.ts +172 -0
  63. package/dist/server/engines/opencode/OpenCodeServerManager.d.ts.map +1 -0
  64. package/dist/server/engines/opencode/OpenCodeServerManager.js +390 -0
  65. package/dist/server/engines/opencode/OpenCodeServerManager.js.map +1 -0
  66. package/dist/server/engines/opencode/model-catalog.d.ts +94 -0
  67. package/dist/server/engines/opencode/model-catalog.d.ts.map +1 -0
  68. package/dist/server/engines/opencode/model-catalog.js +141 -0
  69. package/dist/server/engines/opencode/model-catalog.js.map +1 -0
  70. package/dist/server/engines/types.d.ts +146 -0
  71. package/dist/server/engines/types.d.ts.map +1 -0
  72. package/dist/server/engines/types.js +4 -0
  73. package/dist/server/engines/types.js.map +1 -0
  74. package/dist/server/index.js +9 -2
  75. package/dist/server/index.js.map +1 -1
  76. package/dist/server/mcp/bouncer-haiku.d.ts +17 -4
  77. package/dist/server/mcp/bouncer-haiku.d.ts.map +1 -1
  78. package/dist/server/mcp/bouncer-haiku.js +8 -124
  79. package/dist/server/mcp/bouncer-haiku.js.map +1 -1
  80. package/dist/server/mcp/bouncer-integration.d.ts +45 -0
  81. package/dist/server/mcp/bouncer-integration.d.ts.map +1 -1
  82. package/dist/server/mcp/bouncer-integration.js +69 -5
  83. package/dist/server/mcp/bouncer-integration.js.map +1 -1
  84. package/dist/server/mcp/classifier/BouncerClassifier.d.ts +34 -0
  85. package/dist/server/mcp/classifier/BouncerClassifier.d.ts.map +1 -0
  86. package/dist/server/mcp/classifier/BouncerClassifier.js +4 -0
  87. package/dist/server/mcp/classifier/BouncerClassifier.js.map +1 -0
  88. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.d.ts +17 -0
  89. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.d.ts.map +1 -0
  90. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js +142 -0
  91. package/dist/server/mcp/classifier/ClaudeBouncerClassifier.js.map +1 -0
  92. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.d.ts +68 -0
  93. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.d.ts.map +1 -0
  94. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.js +182 -0
  95. package/dist/server/mcp/classifier/OpenCodeBouncerClassifier.js.map +1 -0
  96. package/dist/server/mcp/classifier/factory.d.ts +70 -0
  97. package/dist/server/mcp/classifier/factory.d.ts.map +1 -0
  98. package/dist/server/mcp/classifier/factory.js +155 -0
  99. package/dist/server/mcp/classifier/factory.js.map +1 -0
  100. package/dist/server/mcp/server.js +52 -0
  101. package/dist/server/mcp/server.js.map +1 -1
  102. package/dist/server/routes/index.d.ts +1 -0
  103. package/dist/server/routes/index.d.ts.map +1 -1
  104. package/dist/server/routes/index.js +1 -0
  105. package/dist/server/routes/index.js.map +1 -1
  106. package/dist/server/routes/internal.d.ts +16 -0
  107. package/dist/server/routes/internal.d.ts.map +1 -0
  108. package/dist/server/routes/internal.js +94 -0
  109. package/dist/server/routes/internal.js.map +1 -0
  110. package/dist/server/services/plan/agent-resolver.d.ts +26 -0
  111. package/dist/server/services/plan/agent-resolver.d.ts.map +1 -0
  112. package/dist/server/services/plan/agent-resolver.js +102 -0
  113. package/dist/server/services/plan/agent-resolver.js.map +1 -0
  114. package/dist/server/services/plan/composer.d.ts.map +1 -1
  115. package/dist/server/services/plan/composer.js +59 -11
  116. package/dist/server/services/plan/composer.js.map +1 -1
  117. package/dist/server/services/plan/executor.d.ts.map +1 -1
  118. package/dist/server/services/plan/executor.js +3 -1
  119. package/dist/server/services/plan/executor.js.map +1 -1
  120. package/dist/server/services/plan/issue-prompt-builder.d.ts.map +1 -1
  121. package/dist/server/services/plan/issue-prompt-builder.js +33 -1
  122. package/dist/server/services/plan/issue-prompt-builder.js.map +1 -1
  123. package/dist/server/services/plan/parser-core.d.ts.map +1 -1
  124. package/dist/server/services/plan/parser-core.js +1 -0
  125. package/dist/server/services/plan/parser-core.js.map +1 -1
  126. package/dist/server/services/plan/types.d.ts +1 -0
  127. package/dist/server/services/plan/types.d.ts.map +1 -1
  128. package/dist/server/services/runtime-info.d.ts +3 -0
  129. package/dist/server/services/runtime-info.d.ts.map +1 -0
  130. package/dist/server/services/runtime-info.js +21 -0
  131. package/dist/server/services/runtime-info.js.map +1 -0
  132. package/dist/server/services/settings.d.ts +76 -2
  133. package/dist/server/services/settings.d.ts.map +1 -1
  134. package/dist/server/services/settings.js +127 -4
  135. package/dist/server/services/settings.js.map +1 -1
  136. package/dist/server/services/websocket/ask-user-question-bridge.d.ts +32 -0
  137. package/dist/server/services/websocket/ask-user-question-bridge.d.ts.map +1 -0
  138. package/dist/server/services/websocket/ask-user-question-bridge.js +115 -0
  139. package/dist/server/services/websocket/ask-user-question-bridge.js.map +1 -0
  140. package/dist/server/services/websocket/git-branch-handlers.d.ts.map +1 -1
  141. package/dist/server/services/websocket/git-branch-handlers.js +19 -6
  142. package/dist/server/services/websocket/git-branch-handlers.js.map +1 -1
  143. package/dist/server/services/websocket/handler.d.ts +25 -1
  144. package/dist/server/services/websocket/handler.d.ts.map +1 -1
  145. package/dist/server/services/websocket/handler.js +84 -2
  146. package/dist/server/services/websocket/handler.js.map +1 -1
  147. package/dist/server/services/websocket/quality-complexity.d.ts.map +1 -1
  148. package/dist/server/services/websocket/quality-complexity.js +78 -26
  149. package/dist/server/services/websocket/quality-complexity.js.map +1 -1
  150. package/dist/server/services/websocket/quality-eta.d.ts +47 -0
  151. package/dist/server/services/websocket/quality-eta.d.ts.map +1 -0
  152. package/dist/server/services/websocket/quality-eta.js +110 -0
  153. package/dist/server/services/websocket/quality-eta.js.map +1 -0
  154. package/dist/server/services/websocket/quality-grading.d.ts +27 -4
  155. package/dist/server/services/websocket/quality-grading.d.ts.map +1 -1
  156. package/dist/server/services/websocket/quality-grading.js +369 -201
  157. package/dist/server/services/websocket/quality-grading.js.map +1 -1
  158. package/dist/server/services/websocket/quality-handlers.d.ts.map +1 -1
  159. package/dist/server/services/websocket/quality-handlers.js +145 -7
  160. package/dist/server/services/websocket/quality-handlers.js.map +1 -1
  161. package/dist/server/services/websocket/quality-operations.d.ts +34 -0
  162. package/dist/server/services/websocket/quality-operations.d.ts.map +1 -0
  163. package/dist/server/services/websocket/quality-operations.js +47 -0
  164. package/dist/server/services/websocket/quality-operations.js.map +1 -0
  165. package/dist/server/services/websocket/quality-persistence.d.ts +9 -0
  166. package/dist/server/services/websocket/quality-persistence.d.ts.map +1 -1
  167. package/dist/server/services/websocket/quality-persistence.js +10 -0
  168. package/dist/server/services/websocket/quality-persistence.js.map +1 -1
  169. package/dist/server/services/websocket/quality-review-agent.d.ts +1 -1
  170. package/dist/server/services/websocket/quality-review-agent.d.ts.map +1 -1
  171. package/dist/server/services/websocket/quality-review-agent.js +105 -56
  172. package/dist/server/services/websocket/quality-review-agent.js.map +1 -1
  173. package/dist/server/services/websocket/quality-service.d.ts +9 -1
  174. package/dist/server/services/websocket/quality-service.d.ts.map +1 -1
  175. package/dist/server/services/websocket/quality-service.js +334 -14
  176. package/dist/server/services/websocket/quality-service.js.map +1 -1
  177. package/dist/server/services/websocket/quality-tools.d.ts +21 -0
  178. package/dist/server/services/websocket/quality-tools.d.ts.map +1 -1
  179. package/dist/server/services/websocket/quality-tools.js +49 -0
  180. package/dist/server/services/websocket/quality-tools.js.map +1 -1
  181. package/dist/server/services/websocket/quality-types.d.ts +35 -2
  182. package/dist/server/services/websocket/quality-types.d.ts.map +1 -1
  183. package/dist/server/services/websocket/quality-types.js +1 -1
  184. package/dist/server/services/websocket/quality-types.js.map +1 -1
  185. package/dist/server/services/websocket/session-handlers.d.ts +3 -1
  186. package/dist/server/services/websocket/session-handlers.d.ts.map +1 -1
  187. package/dist/server/services/websocket/session-handlers.js +60 -9
  188. package/dist/server/services/websocket/session-handlers.js.map +1 -1
  189. package/dist/server/services/websocket/session-history.js +3 -0
  190. package/dist/server/services/websocket/session-history.js.map +1 -1
  191. package/dist/server/services/websocket/session-initialization.d.ts.map +1 -1
  192. package/dist/server/services/websocket/session-initialization.js +158 -42
  193. package/dist/server/services/websocket/session-initialization.js.map +1 -1
  194. package/dist/server/services/websocket/session-registry.d.ts +25 -0
  195. package/dist/server/services/websocket/session-registry.d.ts.map +1 -1
  196. package/dist/server/services/websocket/session-registry.js +19 -0
  197. package/dist/server/services/websocket/session-registry.js.map +1 -1
  198. package/dist/server/services/websocket/settings-handlers.d.ts +1 -1
  199. package/dist/server/services/websocket/settings-handlers.d.ts.map +1 -1
  200. package/dist/server/services/websocket/settings-handlers.js +35 -4
  201. package/dist/server/services/websocket/settings-handlers.js.map +1 -1
  202. package/dist/server/services/websocket/tab-broadcast.d.ts +7 -2
  203. package/dist/server/services/websocket/tab-broadcast.d.ts.map +1 -1
  204. package/dist/server/services/websocket/tab-broadcast.js +10 -2
  205. package/dist/server/services/websocket/tab-broadcast.js.map +1 -1
  206. package/dist/server/services/websocket/tab-event-buffer.d.ts +97 -8
  207. package/dist/server/services/websocket/tab-event-buffer.d.ts.map +1 -1
  208. package/dist/server/services/websocket/tab-event-buffer.js +138 -12
  209. package/dist/server/services/websocket/tab-event-buffer.js.map +1 -1
  210. package/dist/server/services/websocket/tab-event-replay.d.ts +29 -13
  211. package/dist/server/services/websocket/tab-event-replay.d.ts.map +1 -1
  212. package/dist/server/services/websocket/tab-event-replay.js +55 -2
  213. package/dist/server/services/websocket/tab-event-replay.js.map +1 -1
  214. package/dist/server/services/websocket/tab-handlers.d.ts +9 -1
  215. package/dist/server/services/websocket/tab-handlers.d.ts.map +1 -1
  216. package/dist/server/services/websocket/tab-handlers.js +47 -2
  217. package/dist/server/services/websocket/tab-handlers.js.map +1 -1
  218. package/dist/server/services/websocket/types.d.ts +67 -7
  219. package/dist/server/services/websocket/types.d.ts.map +1 -1
  220. package/dist/server/services/websocket/types.js +12 -6
  221. package/dist/server/services/websocket/types.js.map +1 -1
  222. package/package.json +5 -3
  223. package/server/cli/eta-estimator.ts +249 -0
  224. package/server/cli/headless/claude-invoker-process.ts +9 -1
  225. package/server/cli/headless/mcp-config.ts +30 -5
  226. package/server/cli/headless/runner.ts +21 -0
  227. package/server/cli/headless/stall-assessor.ts +93 -0
  228. package/server/cli/headless/tool-watchdog.ts +21 -0
  229. package/server/cli/headless/types.ts +16 -1
  230. package/server/cli/improvisation-history-store.ts +4 -1
  231. package/server/cli/improvisation-output-queue.ts +29 -7
  232. package/server/cli/improvisation-session-manager.ts +63 -1
  233. package/server/cli/improvisation-types.ts +9 -0
  234. package/server/cli/retry/retry-runner-factory.ts +1 -0
  235. package/server/engines/EngineEvent.ts +156 -0
  236. package/server/engines/claude/ClaudeCodeEngine.ts +404 -0
  237. package/server/engines/factory.ts +176 -0
  238. package/server/engines/opencode/OpenCodeEngine.ts +786 -0
  239. package/server/engines/opencode/OpenCodeServerManager.ts +577 -0
  240. package/server/engines/opencode/model-catalog.ts +217 -0
  241. package/server/engines/types.ts +173 -0
  242. package/server/index.ts +9 -1
  243. package/server/mcp/bouncer-haiku.ts +21 -145
  244. package/server/mcp/bouncer-integration.ts +107 -5
  245. package/server/mcp/classifier/BouncerClassifier.ts +40 -0
  246. package/server/mcp/classifier/ClaudeBouncerClassifier.ts +189 -0
  247. package/server/mcp/classifier/OpenCodeBouncerClassifier.ts +305 -0
  248. package/server/mcp/classifier/factory.ts +195 -0
  249. package/server/mcp/server.ts +57 -0
  250. package/server/routes/index.ts +1 -0
  251. package/server/routes/internal.ts +112 -0
  252. package/server/services/plan/agent-resolver.ts +115 -0
  253. package/server/services/plan/agents/code-review.md +38 -8
  254. package/server/services/plan/composer.ts +63 -11
  255. package/server/services/plan/executor.ts +3 -1
  256. package/server/services/plan/issue-prompt-builder.ts +39 -1
  257. package/server/services/plan/parser-core.ts +1 -0
  258. package/server/services/plan/types.ts +4 -0
  259. package/server/services/runtime-info.ts +24 -0
  260. package/server/services/settings.ts +161 -4
  261. package/server/services/websocket/ask-user-question-bridge.ts +148 -0
  262. package/server/services/websocket/git-branch-handlers.ts +20 -6
  263. package/server/services/websocket/handler.ts +89 -2
  264. package/server/services/websocket/quality-complexity.ts +80 -26
  265. package/server/services/websocket/quality-eta.ts +155 -0
  266. package/server/services/websocket/quality-grading.ts +445 -222
  267. package/server/services/websocket/quality-handlers.ts +153 -7
  268. package/server/services/websocket/quality-operations.ts +72 -0
  269. package/server/services/websocket/quality-persistence.ts +17 -0
  270. package/server/services/websocket/quality-review-agent.ts +154 -64
  271. package/server/services/websocket/quality-service.ts +361 -13
  272. package/server/services/websocket/quality-tools.ts +51 -0
  273. package/server/services/websocket/quality-types.ts +41 -2
  274. package/server/services/websocket/session-handlers.ts +67 -10
  275. package/server/services/websocket/session-history.ts +3 -0
  276. package/server/services/websocket/session-initialization.ts +189 -46
  277. package/server/services/websocket/session-registry.ts +37 -0
  278. package/server/services/websocket/settings-handlers.ts +41 -4
  279. package/server/services/websocket/tab-broadcast.ts +10 -2
  280. package/server/services/websocket/tab-event-buffer.ts +143 -11
  281. package/server/services/websocket/tab-event-replay.ts +70 -3
  282. package/server/services/websocket/tab-handlers.ts +53 -5
  283. package/server/services/websocket/types.ts +85 -7
@@ -0,0 +1,172 @@
1
+ /**
2
+ * OpenCodeServerManager — lifecycle owner for a single `opencode serve`
3
+ * subprocess per CLI instance.
4
+ *
5
+ * Responsibilities:
6
+ * - Lazy start: the subprocess is spawned on the first `start()` call.
7
+ * - Idempotent start: concurrent callers share a single subprocess and a
8
+ * single in-flight start Promise.
9
+ * - Health-gated readiness: `start()` resolves only after the subprocess has
10
+ * both (a) printed its listening URL and (b) responded to an HTTP probe.
11
+ * - Crash detection with exponential backoff: an unexpected process exit
12
+ * triggers automatic restart; after `maxRestartAttempts` failures the
13
+ * manager transitions to a terminal `failed` state and further calls
14
+ * reject.
15
+ * - Clean shutdown: `shutdown()` kills the subprocess, prevents further
16
+ * restarts, and (when registerProcessHandlers is set) is wired to CLI
17
+ * exit signals so no orphan process survives the parent.
18
+ *
19
+ * Callers obtain a typed `OpencodeClient` via `getClient()`. The client is
20
+ * stable across restarts — its baseUrl is updated in place when the
21
+ * subprocess is restarted on the same hostname/port.
22
+ */
23
+ import type { ChildProcess, SpawnOptions } from 'node:child_process';
24
+ import { EventEmitter } from 'node:events';
25
+ import { type OpencodeClient } from '@opencode-ai/sdk';
26
+ /** Spawn signature accepted by the manager — matches node's `child_process.spawn`. */
27
+ export type SpawnFn = (command: string, args: readonly string[], options: SpawnOptions) => ChildProcess;
28
+ /** Events emitted by the manager for observability and tests. */
29
+ export type OpenCodeServerEvent = {
30
+ kind: 'starting';
31
+ attempt: number;
32
+ } | {
33
+ kind: 'ready';
34
+ url: string;
35
+ pid: number | undefined;
36
+ } | {
37
+ kind: 'crash';
38
+ code: number | null;
39
+ signal: NodeJS.Signals | null;
40
+ } | {
41
+ kind: 'restart-scheduled';
42
+ attempt: number;
43
+ delayMs: number;
44
+ } | {
45
+ kind: 'failed';
46
+ error: Error;
47
+ } | {
48
+ kind: 'shutdown';
49
+ };
50
+ /** Construction options for {@link OpenCodeServerManager}. */
51
+ export interface OpenCodeServerManagerOptions {
52
+ /** Host the opencode server binds to. Defaults to `127.0.0.1`. */
53
+ hostname?: string;
54
+ /** Port the opencode server binds to. Defaults to `4096`. */
55
+ port?: number;
56
+ /** Binary to invoke. Defaults to `opencode`. Tests override with a shim. */
57
+ command?: string;
58
+ /**
59
+ * Extra args appended to the spawned command. The manager always passes
60
+ * `serve --hostname=<h> --port=<p>` first; overrides may supply the
61
+ * entire arg list by setting `overrideArgs`.
62
+ */
63
+ extraArgs?: string[];
64
+ /**
65
+ * If set, the manager uses exactly these args instead of the default
66
+ * `serve --hostname --port` trio. Tests use this to drive shims that
67
+ * don't implement the opencode CLI.
68
+ */
69
+ overrideArgs?: string[];
70
+ /** Additional env vars merged into the subprocess environment. */
71
+ env?: Record<string, string>;
72
+ /**
73
+ * Milliseconds to wait for the subprocess to emit its readiness line
74
+ * before giving up on an attempt. Defaults to 10_000.
75
+ */
76
+ startTimeoutMs?: number;
77
+ /**
78
+ * Milliseconds between HTTP readiness probes after the readiness line
79
+ * has been seen. Defaults to 50.
80
+ */
81
+ healthPollIntervalMs?: number;
82
+ /**
83
+ * Overall budget for the HTTP readiness probe phase. Defaults to
84
+ * 5_000.
85
+ */
86
+ healthTimeoutMs?: number;
87
+ /**
88
+ * Path used for the HTTP readiness probe. Defaults to `/config`.
89
+ */
90
+ healthPath?: string;
91
+ /** Cap on restart attempts before the manager transitions to `failed`. */
92
+ maxRestartAttempts?: number;
93
+ /** Base backoff for restarts. Doubles each attempt. Defaults to 500ms. */
94
+ initialBackoffMs?: number;
95
+ /** Ceiling for exponential backoff. Defaults to 10_000ms. */
96
+ maxBackoffMs?: number;
97
+ /**
98
+ * If true, the manager registers SIGINT/SIGTERM/exit handlers on the
99
+ * parent process and calls `shutdown()` when they fire. Defaults to
100
+ * false (opt-in at the call site that owns the process-level policy).
101
+ */
102
+ registerProcessHandlers?: boolean;
103
+ /** Inject a fake spawn function for tests. Defaults to node's spawn. */
104
+ spawnFn?: SpawnFn;
105
+ /**
106
+ * Inject a fake fetch for HTTP readiness probes. Defaults to global
107
+ * `fetch`. Primarily used to decouple tests from network timing.
108
+ */
109
+ fetchFn?: typeof fetch;
110
+ }
111
+ /** Lifecycle state for the manager. */
112
+ export type OpenCodeServerStatus = 'idle' | 'starting' | 'ready' | 'restarting' | 'failed' | 'shutdown';
113
+ /**
114
+ * Thrown when the manager has been shut down or has exceeded its restart
115
+ * budget. Callers should construct a new manager to retry.
116
+ */
117
+ export declare class OpenCodeServerManagerClosedError extends Error {
118
+ constructor(message: string);
119
+ }
120
+ export declare class OpenCodeServerManager extends EventEmitter {
121
+ private readonly opts;
122
+ private status;
123
+ private proc;
124
+ private url;
125
+ private startPromise;
126
+ private restartTimer;
127
+ private restartAttempts;
128
+ private failureReason;
129
+ /** Intentional shutdown flag — prevents crash handler from restarting. */
130
+ private isShuttingDown;
131
+ /** Cached SDK client; its baseUrl is rotated on each successful start. */
132
+ private cachedClient;
133
+ private lastBaseUrl;
134
+ private processHandlersRegistered;
135
+ private readonly boundProcessHandler;
136
+ constructor(options?: OpenCodeServerManagerOptions);
137
+ private static resolveOptions;
138
+ /** Current lifecycle state. */
139
+ getStatus(): OpenCodeServerStatus;
140
+ /** URL of the running subprocess, or `null` if not ready. */
141
+ getUrl(): string | null;
142
+ /** True once `start()` has resolved and the subprocess is alive. */
143
+ isRunning(): boolean;
144
+ /**
145
+ * Return a typed SDK client bound to the currently running server.
146
+ * Throws if the manager has not been started or has entered a terminal
147
+ * state.
148
+ */
149
+ getClient(): OpencodeClient;
150
+ /**
151
+ * Idempotent: first call spawns the subprocess; concurrent calls share
152
+ * the same in-flight Promise. Returns after the subprocess is both
153
+ * listening (stdout readiness line seen) and answering HTTP probes.
154
+ */
155
+ start(): Promise<void>;
156
+ /**
157
+ * Terminate the subprocess, cancel any pending restart, and move the
158
+ * manager to the terminal `shutdown` state. Idempotent.
159
+ */
160
+ shutdown(): Promise<void>;
161
+ private emitEvent;
162
+ private buildArgs;
163
+ private spawnOnce;
164
+ private runStartupPhase;
165
+ private awaitReadinessLine;
166
+ private awaitHealthy;
167
+ private wireCrashHandler;
168
+ private scheduleRestart;
169
+ private attachProcessHandlers;
170
+ private detachProcessHandlers;
171
+ }
172
+ //# sourceMappingURL=OpenCodeServerManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenCodeServerManager.d.ts","sourceRoot":"","sources":["../../../../server/engines/opencode/OpenCodeServerManager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,390 @@
1
+ // Copyright (c) 2025-present Mstro, Inc. All rights reserved.
2
+ // Licensed under the MIT License. See LICENSE file for details.
3
+ import { spawn as nodeSpawn } from 'node:child_process';
4
+ import { EventEmitter } from 'node:events';
5
+ import { createOpencodeClient, } from '@opencode-ai/sdk';
6
+ const DEFAULTS = {
7
+ hostname: '127.0.0.1',
8
+ port: 4096,
9
+ command: 'opencode',
10
+ startTimeoutMs: 10_000,
11
+ healthPollIntervalMs: 50,
12
+ healthTimeoutMs: 5_000,
13
+ healthPath: '/config',
14
+ maxRestartAttempts: 5,
15
+ initialBackoffMs: 500,
16
+ maxBackoffMs: 10_000,
17
+ };
18
+ /**
19
+ * Thrown when the manager has been shut down or has exceeded its restart
20
+ * budget. Callers should construct a new manager to retry.
21
+ */
22
+ export class OpenCodeServerManagerClosedError extends Error {
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = 'OpenCodeServerManagerClosedError';
26
+ }
27
+ }
28
+ export class OpenCodeServerManager extends EventEmitter {
29
+ opts;
30
+ status = 'idle';
31
+ proc = null;
32
+ url = null;
33
+ startPromise = null;
34
+ restartTimer = null;
35
+ restartAttempts = 0;
36
+ failureReason = null;
37
+ /** Intentional shutdown flag — prevents crash handler from restarting. */
38
+ isShuttingDown = false;
39
+ /** Cached SDK client; its baseUrl is rotated on each successful start. */
40
+ cachedClient = null;
41
+ lastBaseUrl = null;
42
+ processHandlersRegistered = false;
43
+ boundProcessHandler;
44
+ constructor(options = {}) {
45
+ super();
46
+ this.opts = OpenCodeServerManager.resolveOptions(options);
47
+ this.boundProcessHandler = () => {
48
+ void this.shutdown().catch(() => { });
49
+ };
50
+ if (this.opts.registerProcessHandlers) {
51
+ this.attachProcessHandlers();
52
+ }
53
+ }
54
+ static resolveOptions(options) {
55
+ return {
56
+ hostname: options.hostname ?? DEFAULTS.hostname,
57
+ port: options.port ?? DEFAULTS.port,
58
+ command: options.command ?? DEFAULTS.command,
59
+ extraArgs: options.extraArgs ?? [],
60
+ overrideArgs: options.overrideArgs,
61
+ env: options.env ?? {},
62
+ startTimeoutMs: options.startTimeoutMs ?? DEFAULTS.startTimeoutMs,
63
+ healthPollIntervalMs: options.healthPollIntervalMs ?? DEFAULTS.healthPollIntervalMs,
64
+ healthTimeoutMs: options.healthTimeoutMs ?? DEFAULTS.healthTimeoutMs,
65
+ healthPath: options.healthPath ?? DEFAULTS.healthPath,
66
+ maxRestartAttempts: options.maxRestartAttempts ?? DEFAULTS.maxRestartAttempts,
67
+ initialBackoffMs: options.initialBackoffMs ?? DEFAULTS.initialBackoffMs,
68
+ maxBackoffMs: options.maxBackoffMs ?? DEFAULTS.maxBackoffMs,
69
+ registerProcessHandlers: options.registerProcessHandlers ?? false,
70
+ spawnFn: options.spawnFn ?? nodeSpawn,
71
+ fetchFn: options.fetchFn ?? fetch,
72
+ };
73
+ }
74
+ /** Current lifecycle state. */
75
+ getStatus() {
76
+ return this.status;
77
+ }
78
+ /** URL of the running subprocess, or `null` if not ready. */
79
+ getUrl() {
80
+ return this.url;
81
+ }
82
+ /** True once `start()` has resolved and the subprocess is alive. */
83
+ isRunning() {
84
+ return this.status === 'ready' && this.proc !== null;
85
+ }
86
+ /**
87
+ * Return a typed SDK client bound to the currently running server.
88
+ * Throws if the manager has not been started or has entered a terminal
89
+ * state.
90
+ */
91
+ getClient() {
92
+ if (this.status === 'shutdown' || this.status === 'failed') {
93
+ throw new OpenCodeServerManagerClosedError(`OpenCodeServerManager is ${this.status}` +
94
+ (this.failureReason ? `: ${this.failureReason.message}` : ''));
95
+ }
96
+ if (!this.url) {
97
+ throw new OpenCodeServerManagerClosedError('OpenCodeServerManager.start() has not completed; no client available');
98
+ }
99
+ if (!this.cachedClient || this.lastBaseUrl !== this.url) {
100
+ this.cachedClient = createOpencodeClient({ baseUrl: this.url });
101
+ this.lastBaseUrl = this.url;
102
+ }
103
+ return this.cachedClient;
104
+ }
105
+ /**
106
+ * Idempotent: first call spawns the subprocess; concurrent calls share
107
+ * the same in-flight Promise. Returns after the subprocess is both
108
+ * listening (stdout readiness line seen) and answering HTTP probes.
109
+ */
110
+ start() {
111
+ if (this.status === 'shutdown' || this.status === 'failed') {
112
+ return Promise.reject(new OpenCodeServerManagerClosedError(`OpenCodeServerManager is ${this.status}` +
113
+ (this.failureReason ? `: ${this.failureReason.message}` : '')));
114
+ }
115
+ if (this.status === 'ready' && this.proc) {
116
+ return Promise.resolve();
117
+ }
118
+ if (this.startPromise) {
119
+ return this.startPromise;
120
+ }
121
+ this.startPromise = this.spawnOnce(1)
122
+ .then(() => {
123
+ this.startPromise = null;
124
+ })
125
+ .catch((err) => {
126
+ this.startPromise = null;
127
+ throw err;
128
+ });
129
+ return this.startPromise;
130
+ }
131
+ /**
132
+ * Terminate the subprocess, cancel any pending restart, and move the
133
+ * manager to the terminal `shutdown` state. Idempotent.
134
+ */
135
+ async shutdown() {
136
+ if (this.status === 'shutdown')
137
+ return;
138
+ this.isShuttingDown = true;
139
+ this.status = 'shutdown';
140
+ if (this.restartTimer) {
141
+ clearTimeout(this.restartTimer);
142
+ this.restartTimer = null;
143
+ }
144
+ const proc = this.proc;
145
+ this.proc = null;
146
+ this.url = null;
147
+ this.cachedClient = null;
148
+ this.lastBaseUrl = null;
149
+ if (proc && proc.exitCode === null && proc.signalCode === null) {
150
+ await killAndWait(proc);
151
+ }
152
+ this.detachProcessHandlers();
153
+ this.emitEvent({ kind: 'shutdown' });
154
+ }
155
+ emitEvent(event) {
156
+ this.emit('event', event);
157
+ this.emit(event.kind, event);
158
+ }
159
+ buildArgs() {
160
+ if (this.opts.overrideArgs)
161
+ return [...this.opts.overrideArgs];
162
+ return [
163
+ 'serve',
164
+ `--hostname=${this.opts.hostname}`,
165
+ `--port=${this.opts.port}`,
166
+ ...this.opts.extraArgs,
167
+ ];
168
+ }
169
+ async spawnOnce(attempt) {
170
+ if (this.isShuttingDown || this.status === 'shutdown') {
171
+ throw new OpenCodeServerManagerClosedError('OpenCodeServerManager is shutdown');
172
+ }
173
+ this.status = attempt === 1 ? 'starting' : 'restarting';
174
+ this.emitEvent({ kind: 'starting', attempt });
175
+ const args = this.buildArgs();
176
+ const proc = this.opts.spawnFn(this.opts.command, args, {
177
+ env: { ...process.env, ...this.opts.env },
178
+ stdio: ['ignore', 'pipe', 'pipe'],
179
+ });
180
+ this.proc = proc;
181
+ const readinessUrl = await this.runStartupPhase(proc, () => this.awaitReadinessLine(proc));
182
+ await this.runStartupPhase(proc, () => this.awaitHealthy(readinessUrl));
183
+ this.url = readinessUrl;
184
+ this.status = 'ready';
185
+ this.restartAttempts = 0;
186
+ this.wireCrashHandler(proc);
187
+ this.emitEvent({ kind: 'ready', url: readinessUrl, pid: proc.pid });
188
+ }
189
+ async runStartupPhase(proc, phase) {
190
+ try {
191
+ return await phase();
192
+ }
193
+ catch (err) {
194
+ // Make sure the subprocess is not left dangling if a phase failed.
195
+ if (proc.exitCode === null && proc.signalCode === null) {
196
+ try {
197
+ proc.kill();
198
+ }
199
+ catch {
200
+ // ignore
201
+ }
202
+ }
203
+ this.proc = null;
204
+ throw err;
205
+ }
206
+ }
207
+ awaitReadinessLine(proc) {
208
+ return new Promise((resolve, reject) => {
209
+ let buffered = '';
210
+ let settled = false;
211
+ const onStdout = (chunk) => {
212
+ if (settled)
213
+ return;
214
+ buffered += chunk.toString();
215
+ const lines = buffered.split('\n');
216
+ for (const line of lines) {
217
+ if (line.startsWith('opencode server listening')) {
218
+ const match = line.match(/on\s+(https?:\/\/[^\s]+)/);
219
+ if (!match) {
220
+ finish(reject, new Error(`Failed to parse opencode readiness line: ${line}`));
221
+ return;
222
+ }
223
+ finish(resolve, match[1]);
224
+ return;
225
+ }
226
+ }
227
+ };
228
+ const onStderr = (chunk) => {
229
+ buffered += chunk.toString();
230
+ };
231
+ const onExit = (code, signal) => {
232
+ const tail = buffered.trim();
233
+ finish(reject, new Error(`opencode subprocess exited before readiness (code=${code}, signal=${signal})` +
234
+ (tail ? `\nOutput: ${tail}` : '')));
235
+ };
236
+ const onError = (err) => finish(reject, err);
237
+ const onTimeout = () => {
238
+ finish(reject, new Error(`Timed out after ${this.opts.startTimeoutMs}ms waiting for opencode to announce readiness`));
239
+ };
240
+ const timer = setTimeout(onTimeout, this.opts.startTimeoutMs);
241
+ function finish(cb, value) {
242
+ if (settled)
243
+ return;
244
+ settled = true;
245
+ clearTimeout(timer);
246
+ proc.stdout?.off('data', onStdout);
247
+ proc.stderr?.off('data', onStderr);
248
+ proc.off('exit', onExit);
249
+ proc.off('error', onError);
250
+ cb(value);
251
+ }
252
+ proc.stdout?.on('data', onStdout);
253
+ proc.stderr?.on('data', onStderr);
254
+ proc.on('exit', onExit);
255
+ proc.on('error', onError);
256
+ });
257
+ }
258
+ async awaitHealthy(baseUrl) {
259
+ const url = baseUrl.replace(/\/$/, '') + this.opts.healthPath;
260
+ const deadline = Date.now() + this.opts.healthTimeoutMs;
261
+ let lastError = null;
262
+ while (Date.now() < deadline) {
263
+ try {
264
+ const res = await this.opts.fetchFn(url, { method: 'GET' });
265
+ // Any 2xx/3xx/4xx response means the server is up and routing;
266
+ // only network failures / 5xx indicate it is not yet ready.
267
+ if (res.status < 500)
268
+ return;
269
+ lastError = new Error(`Health probe status ${res.status}`);
270
+ }
271
+ catch (err) {
272
+ lastError = err;
273
+ }
274
+ await sleep(this.opts.healthPollIntervalMs);
275
+ }
276
+ throw new Error(`opencode server did not pass health check at ${url} within ` +
277
+ `${this.opts.healthTimeoutMs}ms` +
278
+ (lastError instanceof Error ? `: ${lastError.message}` : ''));
279
+ }
280
+ wireCrashHandler(proc) {
281
+ const onExit = (code, signal) => {
282
+ if (this.proc !== proc)
283
+ return;
284
+ if (this.isShuttingDown || this.status === 'shutdown')
285
+ return;
286
+ this.proc = null;
287
+ this.url = null;
288
+ this.cachedClient = null;
289
+ this.lastBaseUrl = null;
290
+ this.emitEvent({ kind: 'crash', code, signal });
291
+ this.scheduleRestart();
292
+ };
293
+ proc.once('exit', onExit);
294
+ }
295
+ scheduleRestart() {
296
+ if (this.isShuttingDown || this.status === 'shutdown')
297
+ return;
298
+ this.restartAttempts += 1;
299
+ if (this.restartAttempts > this.opts.maxRestartAttempts) {
300
+ const err = new Error(`opencode subprocess exceeded ${this.opts.maxRestartAttempts} restart attempts`);
301
+ this.failureReason = err;
302
+ this.status = 'failed';
303
+ this.emitEvent({ kind: 'failed', error: err });
304
+ return;
305
+ }
306
+ const delay = Math.min(this.opts.initialBackoffMs * 2 ** (this.restartAttempts - 1), this.opts.maxBackoffMs);
307
+ this.status = 'restarting';
308
+ this.emitEvent({
309
+ kind: 'restart-scheduled',
310
+ attempt: this.restartAttempts,
311
+ delayMs: delay,
312
+ });
313
+ this.restartTimer = setTimeout(() => {
314
+ this.restartTimer = null;
315
+ if (this.isShuttingDown || this.status === 'shutdown')
316
+ return;
317
+ const attempt = this.restartAttempts + 1;
318
+ // spawnOnce uses `attempt` purely for events; we pass the 1-based
319
+ // restart attempt so observers can correlate.
320
+ this.startPromise = this.spawnOnce(attempt)
321
+ .then(() => {
322
+ this.startPromise = null;
323
+ })
324
+ .catch((err) => {
325
+ this.startPromise = null;
326
+ if (this.isShuttingDown || this.status === 'shutdown')
327
+ return;
328
+ this.emitEvent({
329
+ kind: 'crash',
330
+ code: null,
331
+ signal: null,
332
+ });
333
+ // A failure to spawn counts the same as a crash — reschedule.
334
+ this.scheduleRestart();
335
+ // Surface the immediate error via the failed handler chain
336
+ // when we eventually give up in scheduleRestart above.
337
+ this.failureReason = err instanceof Error ? err : new Error(String(err));
338
+ });
339
+ }, delay);
340
+ }
341
+ attachProcessHandlers() {
342
+ if (this.processHandlersRegistered)
343
+ return;
344
+ this.processHandlersRegistered = true;
345
+ process.on('SIGINT', this.boundProcessHandler);
346
+ process.on('SIGTERM', this.boundProcessHandler);
347
+ process.on('beforeExit', this.boundProcessHandler);
348
+ }
349
+ detachProcessHandlers() {
350
+ if (!this.processHandlersRegistered)
351
+ return;
352
+ this.processHandlersRegistered = false;
353
+ process.off('SIGINT', this.boundProcessHandler);
354
+ process.off('SIGTERM', this.boundProcessHandler);
355
+ process.off('beforeExit', this.boundProcessHandler);
356
+ }
357
+ }
358
+ function sleep(ms) {
359
+ return new Promise((resolve) => setTimeout(resolve, ms));
360
+ }
361
+ async function killAndWait(proc) {
362
+ if (proc.exitCode !== null || proc.signalCode !== null)
363
+ return;
364
+ const exited = new Promise((resolve) => {
365
+ proc.once('exit', () => resolve());
366
+ });
367
+ try {
368
+ proc.kill('SIGTERM');
369
+ }
370
+ catch {
371
+ // already exited or permission denied — fall through
372
+ }
373
+ const timer = setTimeout(() => {
374
+ if (proc.exitCode === null && proc.signalCode === null) {
375
+ try {
376
+ proc.kill('SIGKILL');
377
+ }
378
+ catch {
379
+ // ignore
380
+ }
381
+ }
382
+ }, 1_000);
383
+ try {
384
+ await exited;
385
+ }
386
+ finally {
387
+ clearTimeout(timer);
388
+ }
389
+ }
390
+ //# sourceMappingURL=OpenCodeServerManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenCodeServerManager.js","sourceRoot":"","sources":["../../../../server/engines/opencode/OpenCodeServerManager.ts"],"names":[],"mappings":"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"}