@polderlabs/bizar 6.2.5 → 6.3.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 (329) hide show
  1. package/.claude/CLAUDE.md +15 -0
  2. package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
  3. package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  4. package/.claude/agents/_shared/SKILLS.md +109 -0
  5. package/.claude/agents/agent-browser.md +80 -0
  6. package/.claude/agents/baldr.md +49 -0
  7. package/.claude/agents/forseti.md +51 -0
  8. package/.claude/agents/frigg.md +42 -0
  9. package/.claude/agents/heimdall.md +33 -0
  10. package/.claude/agents/hermod.md +53 -0
  11. package/.claude/agents/mimir.md +49 -0
  12. package/.claude/agents/odin.md +287 -0
  13. package/.claude/agents/quick.md +34 -0
  14. package/.claude/agents/semble-search.md +50 -0
  15. package/.claude/agents/thor.md +53 -0
  16. package/.claude/agents/tyr.md +56 -0
  17. package/.claude/agents/vidarr.md +54 -0
  18. package/.claude/agents/vor.md +53 -0
  19. package/.claude/commands/audit.md +25 -0
  20. package/.claude/commands/bizar.md +22 -0
  21. package/.claude/commands/explain.md +17 -0
  22. package/.claude/commands/init.md +29 -0
  23. package/.claude/commands/learn.md +44 -0
  24. package/.claude/commands/plan.md +35 -0
  25. package/.claude/commands/plow-through.md +50 -0
  26. package/.claude/commands/pr-review.md +49 -0
  27. package/.claude/commands/setup-provider.md +96 -0
  28. package/.claude/commands/tailscale-serve.md +100 -0
  29. package/.claude/commands/team.md +132 -0
  30. package/.claude/commands/test.md +62 -0
  31. package/.claude/commands/validate.md +68 -0
  32. package/.claude/commands/visual-plan.md +24 -0
  33. package/.claude/hooks/README.md +92 -0
  34. package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  35. package/.claude/hooks/pretooluse-bash.mjs +81 -0
  36. package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
  37. package/.claude/hooks/sessionend-recall.mjs +74 -0
  38. package/.claude/hooks/sessionstart-prime.mjs +80 -0
  39. package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
  40. package/.claude/settings.json +116 -0
  41. package/.claude/skills/9router/SKILL.md +80 -0
  42. package/.claude/skills/9router-chat/SKILL.md +73 -0
  43. package/.claude/skills/9router-embeddings/SKILL.md +69 -0
  44. package/.claude/skills/9router-image/SKILL.md +86 -0
  45. package/.claude/skills/9router-stt/SKILL.md +79 -0
  46. package/.claude/skills/9router-tts/SKILL.md +80 -0
  47. package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  48. package/.claude/skills/9router-web-search/SKILL.md +91 -0
  49. package/.claude/skills/bizar/README.md +9 -0
  50. package/.claude/skills/bizar/SKILL.md +450 -0
  51. package/.claude/skills/cpp-coding-standards/README.md +28 -0
  52. package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  53. package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  54. package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  55. package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  56. package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  57. package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  58. package/.claude/skills/cpp-testing/README.md +28 -0
  59. package/.claude/skills/cpp-testing/SKILL.md +304 -0
  60. package/.claude/skills/cpp-testing/references/coverage.md +370 -0
  61. package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  62. package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  63. package/.claude/skills/cpp-testing/references/mocking.md +364 -0
  64. package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  65. package/.claude/skills/cubesandbox/SKILL.md +148 -0
  66. package/.claude/skills/embedded-esp-idf/README.md +41 -0
  67. package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  68. package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  69. package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  70. package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  71. package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  72. package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  73. package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  74. package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  75. package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  76. package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  77. package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  78. package/.claude/skills/glyph/SKILL.md +163 -0
  79. package/.claude/skills/harness-engineering/SKILL.md +143 -0
  80. package/.claude/skills/lightrag/SKILL.md +81 -0
  81. package/.claude/skills/memory-protocol/SKILL.md +105 -0
  82. package/.claude/skills/obsidian/SKILL.md +306 -0
  83. package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  84. package/.claude/skills/self-improvement/SKILL.md +64 -0
  85. package/README.md +87 -59
  86. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-B58aiJiE.js} +1 -1
  87. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-B58aiJiE.js.map} +1 -1
  88. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js → MobileChat-BJrqwVDd.js} +1 -1
  89. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-BJrqwVDd.js.map} +1 -1
  90. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js → MobileSettings-CEQNJNLJ.js} +1 -1
  91. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-CEQNJNLJ.js.map} +1 -1
  92. package/bizar-dash/dist/assets/{main-DYiZqMrn.js → main-IvfQAOfy.js} +1 -1
  93. package/bizar-dash/dist/assets/{main-DYiZqMrn.js.map → main-IvfQAOfy.js.map} +1 -1
  94. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js → markdown-tOLaD6nm.js} +1 -1
  95. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-tOLaD6nm.js.map} +1 -1
  96. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js → mobile-DYCHcUpq.js} +1 -1
  97. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DYCHcUpq.js.map} +1 -1
  98. package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js → mobile-layout-CBHjpwsb.js} +2 -2
  99. package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js.map → mobile-layout-CBHjpwsb.js.map} +1 -1
  100. package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js → useSlashCommands-Bd7_FA6U.js} +2 -2
  101. package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js.map → useSlashCommands-Bd7_FA6U.js.map} +1 -1
  102. package/bizar-dash/dist/assets/{vendor-CeHGtduv.js → vendor-C843201K.js} +12 -12
  103. package/bizar-dash/dist/assets/vendor-C843201K.js.map +1 -0
  104. package/bizar-dash/dist/index.html +6 -6
  105. package/bizar-dash/dist/mobile.html +2 -2
  106. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  107. package/bizar-dash/src/server/api.mjs +4 -4
  108. package/bizar-dash/src/server/background-store.mjs +15 -16
  109. package/bizar-dash/src/server/bg-poller.mjs +25 -35
  110. package/bizar-dash/src/server/bg-retry.mjs +66 -194
  111. package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  112. package/bizar-dash/src/server/claude-info.mjs +412 -0
  113. package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
  114. package/bizar-dash/src/server/claude-sdk.mjs +191 -0
  115. package/bizar-dash/src/server/providers-store.mjs +22 -49
  116. package/bizar-dash/src/server/routes/background.mjs +24 -20
  117. package/bizar-dash/src/server/routes/chat.mjs +223 -326
  118. package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  119. package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  120. package/bizar-dash/src/server/routes/tasks.mjs +20 -28
  121. package/bizar-dash/src/server/task-delegator.mjs +76 -77
  122. package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
  123. package/bizar-dash/src/web/views/Chat.tsx +8 -8
  124. package/cli/bin.mjs +17 -18
  125. package/cli/commands/claude-cmd.mjs +348 -0
  126. package/cli/commands/install.mjs +12 -11
  127. package/cli/commands/validate.mjs +252 -325
  128. package/cli/dev-link.test.mjs +11 -11
  129. package/cli/doctor.mjs +131 -213
  130. package/cli/install.mjs +33 -37
  131. package/cli/install.test.mjs +9 -9
  132. package/cli/provision-claude.mjs +893 -0
  133. package/cli/provision.mjs +224 -227
  134. package/cli/utils.mjs +72 -58
  135. package/config/AGENTS.md +28 -28
  136. package/install.sh +66 -44
  137. package/package.json +19 -11
  138. package/packages/sdk/ARCHITECTURE.md +40 -36
  139. package/packages/sdk/package-lock.json +32 -0
  140. package/packages/sdk/package.json +15 -5
  141. package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
  142. package/packages/sdk/src/fingerprint.ts +0 -0
  143. package/packages/sdk/src/index.ts +38 -73
  144. package/packages/sdk/src/mcp/bin.ts +51 -0
  145. package/packages/sdk/src/mcp/server.ts +498 -0
  146. package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
  147. package/packages/sdk/tests/sdk.test.mjs +148 -0
  148. package/packages/sdk/vitest.config.ts +1 -1
  149. package/scripts/bh-full-e2e.mjs +166 -363
  150. package/scripts/check-deps.mjs +28 -46
  151. package/scripts/mirror-claude-md.sh +78 -0
  152. package/scripts/test-in-container.sh +31 -9
  153. package/templates/clean-state-checklist.md +3 -3
  154. package/templates/sprint-contract.md +2 -2
  155. package/bizar-dash/.bizar/activity.log +0 -3
  156. package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
  157. package/bizar-dash/.omx/state/session.json +0 -10
  158. package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
  159. package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
  160. package/bizar-dash/bizar-design/canvas.html +0 -281
  161. package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
  162. package/bizar-dash/bizar-design/components.css +0 -1665
  163. package/bizar-dash/bizar-design/components.html +0 -557
  164. package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
  165. package/bizar-dash/bizar-design/desktop/agents.html +0 -74
  166. package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
  167. package/bizar-dash/bizar-design/desktop/memory.html +0 -75
  168. package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
  169. package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
  170. package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
  171. package/bizar-dash/bizar-design/desktop/overview.html +0 -95
  172. package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
  173. package/bizar-dash/bizar-design/desktop/settings.html +0 -70
  174. package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
  175. package/bizar-dash/bizar-design/icons.svg +0 -44
  176. package/bizar-dash/bizar-design/index.html +0 -192
  177. package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
  178. package/bizar-dash/bizar-design/mobile/agents.html +0 -29
  179. package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
  180. package/bizar-dash/bizar-design/mobile/memory.html +0 -28
  181. package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
  182. package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
  183. package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
  184. package/bizar-dash/bizar-design/mobile/overview.html +0 -33
  185. package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
  186. package/bizar-dash/bizar-design/mobile/settings.html +0 -28
  187. package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
  188. package/bizar-dash/bizar-design/prototype.js +0 -114
  189. package/bizar-dash/bizar-design/tokens.css +0 -106
  190. package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
  191. package/bizar-dash/node_modules/.package-lock.json +0 -6
  192. package/bizar-dash/package-lock.json +0 -6
  193. package/bizar-dash/src/server/cline-sdk.mjs +0 -132
  194. package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
  195. package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
  196. package/cli/commands/cline-cmd.mjs +0 -289
  197. package/cli/commands/validate.test.mjs +0 -379
  198. package/cli/doctor.test.mjs +0 -350
  199. package/config/cline.json.template +0 -342
  200. package/packages/sdk/src/client.ts +0 -188
  201. package/packages/sdk/src/cline-events.ts +0 -134
  202. package/packages/sdk/src/cline-types.ts +0 -66
  203. package/packages/sdk/src/cline.ts +0 -339
  204. package/packages/sdk/src/errors.ts +0 -129
  205. package/packages/sdk/src/events.ts +0 -153
  206. package/packages/sdk/src/types.ts +0 -176
  207. package/packages/sdk/tests/client.test.ts +0 -217
  208. package/packages/sdk/tests/errors.test.ts +0 -108
  209. package/packages/sdk/tests/events.test.ts +0 -139
  210. package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
  211. package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
  212. package/plugins/bizar/ARCHITECTURE.md +0 -142
  213. package/plugins/bizar/CONSTRAINTS.md +0 -67
  214. package/plugins/bizar/LICENSE +0 -21
  215. package/plugins/bizar/README.md +0 -448
  216. package/plugins/bizar/index.ts +0 -925
  217. package/plugins/bizar/package.json +0 -39
  218. package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
  219. package/plugins/bizar/src/background-state.ts +0 -641
  220. package/plugins/bizar/src/background.ts +0 -1806
  221. package/plugins/bizar/src/cline-runner.ts +0 -203
  222. package/plugins/bizar/src/clineruntime.ts +0 -227
  223. package/plugins/bizar/src/commands-impl.ts +0 -151
  224. package/plugins/bizar/src/commands.ts +0 -1799
  225. package/plugins/bizar/src/compaction.d.mts +0 -48
  226. package/plugins/bizar/src/compaction.mjs +0 -192
  227. package/plugins/bizar/src/dashboard-client.ts +0 -233
  228. package/plugins/bizar/src/event-stream.ts +0 -606
  229. package/plugins/bizar/src/fingerprint.ts +0 -120
  230. package/plugins/bizar/src/handoff.ts +0 -79
  231. package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
  232. package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
  233. package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
  234. package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
  235. package/plugins/bizar/src/http-client.ts +0 -467
  236. package/plugins/bizar/src/key-rotation.ts +0 -218
  237. package/plugins/bizar/src/logger.ts +0 -144
  238. package/plugins/bizar/src/loop-engineering.ts +0 -241
  239. package/plugins/bizar/src/loop.ts +0 -176
  240. package/plugins/bizar/src/mistake-recovery.ts +0 -98
  241. package/plugins/bizar/src/odin.ts +0 -227
  242. package/plugins/bizar/src/options.ts +0 -470
  243. package/plugins/bizar/src/plan-fs.ts +0 -323
  244. package/plugins/bizar/src/reasoning-clean.ts +0 -454
  245. package/plugins/bizar/src/report.ts +0 -178
  246. package/plugins/bizar/src/research-prompt.ts +0 -35
  247. package/plugins/bizar/src/serve-info.ts +0 -228
  248. package/plugins/bizar/src/serve.ts +0 -496
  249. package/plugins/bizar/src/settings.ts +0 -349
  250. package/plugins/bizar/src/state.ts +0 -298
  251. package/plugins/bizar/src/tool-discipline.ts +0 -105
  252. package/plugins/bizar/src/tools/agent-browser.ts +0 -315
  253. package/plugins/bizar/src/tools/bg-collect.ts +0 -131
  254. package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
  255. package/plugins/bizar/src/tools/bg-kill.ts +0 -116
  256. package/plugins/bizar/src/tools/bg-pause.ts +0 -99
  257. package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
  258. package/plugins/bizar/src/tools/bg-resume.ts +0 -94
  259. package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
  260. package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
  261. package/plugins/bizar/src/tools/bg-status.ts +0 -130
  262. package/plugins/bizar/src/tools/graph-query.ts +0 -278
  263. package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
  264. package/plugins/bizar/src/tools/memory-list.ts +0 -43
  265. package/plugins/bizar/src/tools/memory-read.ts +0 -69
  266. package/plugins/bizar/src/tools/memory-search.ts +0 -47
  267. package/plugins/bizar/src/tools/memory-write.ts +0 -54
  268. package/plugins/bizar/src/tools/open-kb.ts +0 -198
  269. package/plugins/bizar/src/tools/plan-action.ts +0 -785
  270. package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
  271. package/plugins/bizar/src/tools/sandbox.ts +0 -232
  272. package/plugins/bizar/src/tools/team-spawn.ts +0 -73
  273. package/plugins/bizar/src/tools/team-status.ts +0 -76
  274. package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
  275. package/plugins/bizar/src/trajectory.ts +0 -104
  276. package/plugins/bizar/tests/README.md +0 -99
  277. package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
  278. package/plugins/bizar/tests/background-state.test.ts +0 -277
  279. package/plugins/bizar/tests/background.test.ts +0 -402
  280. package/plugins/bizar/tests/block.test.ts +0 -195
  281. package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
  282. package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
  283. package/plugins/bizar/tests/commands-impl.test.ts +0 -316
  284. package/plugins/bizar/tests/commands.test.ts +0 -584
  285. package/plugins/bizar/tests/compaction.test.ts +0 -264
  286. package/plugins/bizar/tests/config.test.ts +0 -128
  287. package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
  288. package/plugins/bizar/tests/dispose.test.ts +0 -336
  289. package/plugins/bizar/tests/event-stream.test.ts +0 -409
  290. package/plugins/bizar/tests/event.test.ts +0 -262
  291. package/plugins/bizar/tests/fingerprint.test.ts +0 -190
  292. package/plugins/bizar/tests/http-client.test.ts +0 -404
  293. package/plugins/bizar/tests/init-helpers.test.ts +0 -203
  294. package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
  295. package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
  296. package/plugins/bizar/tests/key-rotation.test.ts +0 -396
  297. package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
  298. package/plugins/bizar/tests/loop.test.ts +0 -397
  299. package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
  300. package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
  301. package/plugins/bizar/tests/odin.test.ts +0 -125
  302. package/plugins/bizar/tests/options.test.ts +0 -329
  303. package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
  304. package/plugins/bizar/tests/safety.test.ts +0 -281
  305. package/plugins/bizar/tests/serve.test.ts +0 -339
  306. package/plugins/bizar/tests/settings.test.ts +0 -351
  307. package/plugins/bizar/tests/stall-think.test.ts +0 -750
  308. package/plugins/bizar/tests/state.test.ts +0 -276
  309. package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
  310. package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
  311. package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
  312. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
  313. package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
  314. package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
  315. package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
  316. package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
  317. package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
  318. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
  319. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
  320. package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
  321. package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
  322. package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
  323. package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
  324. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
  325. package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
  326. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
  327. package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
  328. package/plugins/bizar/tsconfig.json +0 -29
  329. package/scripts/mirror-agents-md.sh +0 -69
@@ -0,0 +1,412 @@
1
+ /**
2
+ * src/server/claude-info.mjs
3
+ *
4
+ * v6.3.0 — Dashboard-side documentation + discovery for the Claude
5
+ * Code runtime. Replaces serve-info.mjs (which documented the Cline
6
+ * HTTP serve subprocess contract).
7
+ *
8
+ * Why this module exists:
9
+ * Claude Code does NOT have an out-of-process serve child like
10
+ * Cline's `cline serve`. Instead, the dashboard talks to the
11
+ * `claude` CLI directly:
12
+ *
13
+ * - `claude -p "<prompt>"` — one-shot, runs to completion
14
+ * - `claude --bg` — background daemon session
15
+ * - `claude --resume <id> -p …` — resume an existing session
16
+ *
17
+ * And the SDK (`@anthropic-ai/claude-agent-sdk`) gives us in-process
18
+ * `query()` + `ClaudeSDKClient` for typed access to streaming events.
19
+ *
20
+ * This module:
21
+ * 1. Documents the CLI flag contract (so other modules don't have
22
+ * to hardcode flag names).
23
+ * 2. Documents the on-disk session storage at `~/.claude/sessions/`.
24
+ * 3. Resolves the `claude` binary path (PATH first, then `npx
25
+ * @anthropic-ai/claude-agent-sdk/cli`).
26
+ * 4. Provides small JSONL helpers for reading session message
27
+ * history that the rest of the dashboard can use.
28
+ *
29
+ * Reference:
30
+ * https://code.claude.com/docs/en/cli-reference
31
+ *
32
+ * No HTTP serve handshake, no Basic auth header, no SQLite DB. Claude
33
+ * Code reads API keys from the environment itself.
34
+ */
35
+
36
+ import { existsSync, readFileSync, readdirSync, rmSync, statSync } from 'node:fs';
37
+ import { homedir } from 'node:os';
38
+ import { join, resolve } from 'node:path';
39
+ import { warn as loggerWarn } from './logger.mjs';
40
+
41
+ const HOME = homedir();
42
+
43
+ /**
44
+ * Canonical on-disk paths for Claude Code.
45
+ *
46
+ * ~/.claude/ — root config + data dir (per Claude docs)
47
+ * ~/.claude/sessions/ — one subdir per session
48
+ * <sessionId>/
49
+ * messages.jsonl — conversation history (one JSON per line)
50
+ *
51
+ * Each messages.jsonl line is one of:
52
+ * - {type:"user", message:{role:"user", content:[...]}}
53
+ * - {type:"assistant", message:{role:"assistant", content:[...]}}
54
+ * - {type:"system", subtype:"init", session_id, model, ...}
55
+ * - {type:"result", subtype:"success"|"error_during_execution", ...}
56
+ */
57
+ export const CLAUDE_HOME = join(HOME, '.claude');
58
+ export const CLAUDE_SESSIONS_DIR = join(CLAUDE_HOME, 'sessions');
59
+
60
+ /**
61
+ * Resolve the `claude` binary path. Tries (in order):
62
+ * 1. `process.env.CLAUDE_BIN` (override)
63
+ * 2. `claude` on PATH (the user-installed case)
64
+ * 3. `npx -y @anthropic-ai/claude-agent-sdk/cli` as a fallback
65
+ *
66
+ * Returns `{ bin, args }` so the caller can construct the right
67
+ * subprocess argv. The fallback uses `npx -y` so a fresh checkout
68
+ * can spawn Claude Code even when the CLI isn't installed globally.
69
+ *
70
+ * @returns {{ bin: string, args: string[] }}
71
+ */
72
+ export function resolveClaudeCommand() {
73
+ if (process.env.CLAUDE_BIN && process.env.CLAUDE_BIN.trim()) {
74
+ return { bin: process.env.CLAUDE_BIN.trim(), args: [] };
75
+ }
76
+ return { bin: 'claude', args: [] };
77
+ }
78
+
79
+ /**
80
+ * Claude Code CLI flag contract (verified against
81
+ * https://code.claude.com/docs/en/cli-reference). Single source of
82
+ * truth — every other module reads flags from here so a Claude
83
+ * update only changes one file.
84
+ */
85
+ export const CLAUDE_CLI_FLAGS = Object.freeze({
86
+ // Print / run modes
87
+ PRINT: '-p',
88
+ BACKGROUND: '--bg',
89
+ RESUME: '--resume',
90
+ SESSION_ID: '--session-id',
91
+ SESSION_TITLE: '--session-title',
92
+
93
+ // Model + agent
94
+ MODEL: '--model',
95
+ AGENT: '--agent',
96
+
97
+ // Working directory
98
+ ADD_DIR: '--add-dir',
99
+
100
+ // Output / wire format
101
+ OUTPUT_FORMAT: '--output-format',
102
+ VERBOSE: '--verbose',
103
+ JSON_FORMAT: 'json',
104
+
105
+ // Permission / autonomy
106
+ PERMISSION_MODE: '--permission-mode',
107
+ PERMISSION_BYPASS: 'bypassPermissions',
108
+ PERMISSION_PLAN: 'plan',
109
+ PERMISSION_DEFAULT: 'default',
110
+
111
+ // MCP + skills
112
+ MCP_CONFIG: '--mcp-config',
113
+
114
+ // Limits
115
+ MAX_TURNS: '--max-turns',
116
+ });
117
+
118
+ /**
119
+ * Claude Code stores sessions as JSONL. Normalize one parsed line
120
+ * into the dashboard's chat shape:
121
+ *
122
+ * { id, role, content, ts, kind? }
123
+ *
124
+ * Accepts both v1 shapes (text directly on the message) and v2
125
+ * shapes (parts / blocks under `content`).
126
+ *
127
+ * @param {object} line one entry from messages.jsonl
128
+ * @returns {{ id: string, role: string, content: string, ts: number, kind?: string }}
129
+ */
130
+ export function normalizeClaudeMessage(line) {
131
+ if (!line || typeof line !== 'object') {
132
+ return { id: '', role: 'assistant', content: '', ts: Date.now() };
133
+ }
134
+ const t = typeof line.type === 'string' ? line.type : null;
135
+ const message = line.message || line;
136
+ const id =
137
+ (typeof message?.id === 'string' && message.id) ||
138
+ (typeof line.id === 'string' && line.id) ||
139
+ (typeof line.uuid === 'string' && line.uuid) ||
140
+ (typeof line.timestamp === 'string' && line.timestamp) ||
141
+ '';
142
+ const role = typeof message?.role === 'string' ? message.role : (t === 'user' ? 'user' : 'assistant');
143
+ const ts =
144
+ (typeof line.timestamp === 'string' ? Date.parse(line.timestamp) : NaN) ||
145
+ (typeof line.ts === 'number' ? line.ts : NaN) ||
146
+ (typeof message?.ts === 'number' ? message.ts : NaN) ||
147
+ Date.now();
148
+ const content = extractClaudeContent(message);
149
+ const out = { id: String(id), role: String(role), content, ts: typeof ts === 'number' && Number.isFinite(ts) ? ts : Date.now() };
150
+ if (t) out.kind = t;
151
+ return out;
152
+ }
153
+
154
+ /**
155
+ * Flatten a Claude Code message's `content` field into a single
156
+ * string. Handles:
157
+ * - string content ("hello")
158
+ * - array of blocks (text, tool_use, tool_result, image, …)
159
+ * - legacy { text } wrapper
160
+ *
161
+ * Non-text blocks are skipped — they don't contribute to the chat
162
+ * surface but still appear in the JSONL for tooling.
163
+ */
164
+ function extractClaudeContent(message) {
165
+ if (!message) return '';
166
+ if (typeof message.text === 'string') return stripThinkingTags(message.text);
167
+ const c = message.content;
168
+ if (typeof c === 'string') return stripThinkingTags(c);
169
+ if (!Array.isArray(c)) return '';
170
+ const text = c
171
+ .filter((p) => p && (p.type === 'text' || typeof p.text === 'string'))
172
+ .map((p) => (typeof p.text === 'string' ? p.text : ''))
173
+ .filter(Boolean)
174
+ .join('\n\n');
175
+ return stripThinkingTags(text);
176
+ }
177
+
178
+ /**
179
+ * Strip `<thinking>...</thinking>` blocks from model output so the
180
+ * chat UI doesn't render them as visible escaped HTML.
181
+ *
182
+ * Same shape as the v5.0.0 cline helper — kept here so chat
183
+ * rendering stays consistent across the migration.
184
+ */
185
+ function stripThinkingTags(text) {
186
+ if (typeof text !== 'string') return '';
187
+ const cleaned = text
188
+ .replace(/<thinking\b[^>]*>[\s\S]*?<\/thinking>/gi, '')
189
+ .replace(/<thinking\b[^>]*\/?>/gi, '')
190
+ .replace(/<\/thinking>/gi, '');
191
+ return cleaned.replace(/\n{3,}/g, '\n\n').trim();
192
+ }
193
+
194
+ /**
195
+ * List every Claude Code session currently on disk. Reads
196
+ * `~/.claude/sessions/` and returns metadata derived from each
197
+ * `messages.jsonl` (first system/init line carries the model +
198
+ * session id; first user message carries the title).
199
+ *
200
+ * Returns `[]` when the directory doesn't exist (a fresh user has
201
+ * never run `claude`). Never throws.
202
+ *
203
+ * @returns {Array<{ id: string, title: string, createdAt: number, updatedAt: number, model?: string }>}
204
+ */
205
+ export function listClaudeSessions() {
206
+ if (!existsSync(CLAUDE_SESSIONS_DIR)) return [];
207
+ let dirs;
208
+ try {
209
+ dirs = readdirSync(CLAUDE_SESSIONS_DIR, { withFileTypes: true })
210
+ .filter((d) => d.isDirectory())
211
+ .map((d) => d.name);
212
+ } catch (err) {
213
+ loggerWarn('claude-info: listClaudeSessions readdir failed', { err: err instanceof Error ? err.message : String(err) });
214
+ return [];
215
+ }
216
+ const out = [];
217
+ for (const id of dirs) {
218
+ const file = join(CLAUDE_SESSIONS_DIR, id, 'messages.jsonl');
219
+ if (!existsSync(file)) continue;
220
+ const meta = readSessionMeta(file, id);
221
+ if (meta) out.push(meta);
222
+ }
223
+ out.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
224
+ return out;
225
+ }
226
+
227
+ /**
228
+ * Read the metadata header for a single session (first init line +
229
+ * first user message + last mtime). Returns `null` on any failure.
230
+ *
231
+ * @param {string} file absolute path to messages.jsonl
232
+ * @param {string} id session id (the directory name)
233
+ */
234
+ function readSessionMeta(file, id) {
235
+ let firstUserText = '';
236
+ let model = '';
237
+ let createdAt = 0;
238
+ let lastTs = 0;
239
+ let size = 0;
240
+ try {
241
+ const stat = statSync(file);
242
+ size = stat.size;
243
+ lastTs = stat.mtimeMs || 0;
244
+ } catch {
245
+ /* fall through — stat is best-effort */
246
+ }
247
+ try {
248
+ const text = readFileSync(file, 'utf8');
249
+ const lines = text.split('\n');
250
+ for (const raw of lines) {
251
+ const line = raw.trim();
252
+ if (!line) continue;
253
+ let parsed;
254
+ try { parsed = JSON.parse(line); } catch { continue; }
255
+ if (parsed?.type === 'system' && parsed?.subtype === 'init') {
256
+ if (typeof parsed.session_id === 'string') id = parsed.session_id;
257
+ if (typeof parsed.model === 'string') model = parsed.model;
258
+ if (typeof parsed.timestamp === 'string') {
259
+ const t = Date.parse(parsed.timestamp);
260
+ if (Number.isFinite(t)) createdAt = createdAt || t;
261
+ }
262
+ }
263
+ if (parsed?.type === 'user' && !firstUserText) {
264
+ const content = parsed?.message?.content;
265
+ if (typeof content === 'string') firstUserText = content;
266
+ else if (Array.isArray(content)) {
267
+ const t = content.find((b) => b && (b.type === 'text' || typeof b.text === 'string'));
268
+ if (t && typeof t.text === 'string') firstUserText = t.text;
269
+ }
270
+ if (typeof parsed.timestamp === 'string') {
271
+ const t = Date.parse(parsed.timestamp);
272
+ if (Number.isFinite(t)) createdAt = createdAt || t;
273
+ }
274
+ }
275
+ if (typeof parsed?.timestamp === 'string') {
276
+ const t = Date.parse(parsed.timestamp);
277
+ if (Number.isFinite(t)) lastTs = Math.max(lastTs, t);
278
+ }
279
+ }
280
+ } catch {
281
+ return null;
282
+ }
283
+ const title = firstUserText
284
+ ? firstUserText.replace(/\s+/g, ' ').trim().slice(0, 80) || `Session ${id}`
285
+ : `Session ${id}`;
286
+ return {
287
+ id,
288
+ title,
289
+ createdAt: createdAt || lastTs || 0,
290
+ updatedAt: lastTs || createdAt || 0,
291
+ model: model || undefined,
292
+ size,
293
+ };
294
+ }
295
+
296
+ /**
297
+ * List every message in a session. Reads `messages.jsonl` from
298
+ * `~/.claude/sessions/<id>/` and normalizes each line via
299
+ * {@link normalizeClaudeMessage}.
300
+ *
301
+ * Returns `{ ok, messages }` on success; `{ ok: false, error }`
302
+ * when the file is missing or unreadable. Never throws.
303
+ *
304
+ * @param {string} sessionId
305
+ * @returns {{ ok: true, messages: ReturnType<typeof normalizeClaudeMessage>[] } | { ok: false, error: string }}
306
+ */
307
+ export function listClaudeMessages(sessionId) {
308
+ if (!sessionId || typeof sessionId !== 'string') {
309
+ return { ok: false, error: 'sessionId is required' };
310
+ }
311
+ const file = join(CLAUDE_SESSIONS_DIR, sessionId, 'messages.jsonl');
312
+ if (!existsSync(file)) {
313
+ return { ok: false, error: `session ${sessionId} not found at ${file}` };
314
+ }
315
+ let text;
316
+ try {
317
+ text = readFileSync(file, 'utf8');
318
+ } catch (err) {
319
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
320
+ }
321
+ const out = [];
322
+ for (const raw of text.split('\n')) {
323
+ const line = raw.trim();
324
+ if (!line) continue;
325
+ let parsed;
326
+ try { parsed = JSON.parse(line); } catch { continue; }
327
+ out.push(normalizeClaudeMessage(parsed));
328
+ }
329
+ return { ok: true, messages: out };
330
+ }
331
+
332
+ /**
333
+ * Read the most recent assistant text from a session — used by the
334
+ * bg-poller's html-artifact scanner (replaces the old
335
+ * `extractContentFromClineMessage` + `listClineMessages` flow).
336
+ *
337
+ * @param {string} sessionId
338
+ * @returns {string}
339
+ */
340
+ export function readLastAssistantText(sessionId) {
341
+ const res = listClaudeMessages(sessionId);
342
+ if (!res.ok) return '';
343
+ for (let i = res.messages.length - 1; i >= 0; i -= 1) {
344
+ const m = res.messages[i];
345
+ if (m && m.role === 'assistant' && m.content) return m.content;
346
+ }
347
+ return '';
348
+ }
349
+
350
+ /**
351
+ * Resolve the on-disk worktree (directory) for a session by looking
352
+ * at the JSONL init line. Claude Code stores `cwd` and `addDir` on
353
+ * the system init event.
354
+ *
355
+ * Returns `null` when the session can't be found or has no cwd field.
356
+ *
357
+ * @param {string} sessionId
358
+ * @returns {string|null}
359
+ */
360
+ export function resolveSessionWorktree(sessionId) {
361
+ if (!sessionId) return null;
362
+ const file = join(CLAUDE_SESSIONS_DIR, sessionId, 'messages.jsonl');
363
+ if (!existsSync(file)) return null;
364
+ try {
365
+ const text = readFileSync(file, 'utf8');
366
+ for (const raw of text.split('\n')) {
367
+ const line = raw.trim();
368
+ if (!line) continue;
369
+ let parsed;
370
+ try { parsed = JSON.parse(line); } catch { continue; }
371
+ if (parsed?.type === 'system' && parsed?.subtype === 'init') {
372
+ if (typeof parsed.cwd === 'string' && parsed.cwd) return resolve(parsed.cwd);
373
+ if (Array.isArray(parsed.addDir) && parsed.addDir.length > 0) {
374
+ const first = parsed.addDir.find((d) => typeof d === 'string' && d);
375
+ if (first) return resolve(first);
376
+ }
377
+ }
378
+ }
379
+ } catch { /* ignore */ }
380
+ return null;
381
+ }
382
+
383
+ /**
384
+ * Best-effort deletion of a session's on-disk directory. Idempotent.
385
+ *
386
+ * @param {string} sessionId
387
+ * @returns {{ ok: boolean, error?: string }}
388
+ */
389
+ export function deleteClaudeSession(sessionId) {
390
+ if (!sessionId || typeof sessionId !== 'string') {
391
+ return { ok: false, error: 'sessionId is required' };
392
+ }
393
+ const dir = join(CLAUDE_SESSIONS_DIR, sessionId);
394
+ if (!existsSync(dir)) return { ok: true };
395
+ try {
396
+ rmSync(dir, { recursive: true, force: true });
397
+ return { ok: true };
398
+ } catch (err) {
399
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
400
+ }
401
+ }
402
+
403
+ // Exposed for tests / introspection.
404
+ export const _claudeInfoInternals = {
405
+ CLAUDE_HOME,
406
+ CLAUDE_SESSIONS_DIR,
407
+ CLAUDE_CLI_FLAGS,
408
+ resolveClaudeCommand,
409
+ normalizeClaudeMessage,
410
+ listClaudeSessions,
411
+ listClaudeMessages,
412
+ };
@@ -1,16 +1,26 @@
1
1
  /**
2
- * bizar-dash/src/server/cline-runner.mjs
2
+ * bizar-dash/src/server/claude-runner.mjs
3
3
  *
4
- * v3.11.1 — Node child_process version of the cline-runner.
4
+ * v6.3.0 — Claude Code-native agent runner. Replaces the legacy
5
+ * cline-runner.mjs that spawned `cline run` subprocesses. This module
6
+ * spawns `claude -p` (print mode, blocking) or `claude --bg`
7
+ * (background, returns session id immediately).
5
8
  *
6
- * The plugin uses Bun.spawn (see plugins/bizar/src/cline-runner.ts);
7
- * the dashboard runs under Node and uses child_process.spawn. This
8
- * module keeps the two implementations in sync — same surface, same
9
- * log-format parsing, same exit semantics.
9
+ * Claude Code's CLI flags (from https://code.claude.com/docs/en/cli-reference):
10
+ * -p "<prompt>" : print mode (run, output, exit)
11
+ * --output-format json : JSON-lines output (one message per line)
12
+ * --model <model> : sonnet | opus | haiku (or full ID)
13
+ * --agent <name> : pre-defined subagent name from .claude/agents/
14
+ * --add-dir <path> : add a working directory
15
+ * --mcp-config <path> : load MCP config from JSON
16
+ * --session-id <id> : resume a specific session
17
+ * --verbose : verbose logging to stderr
10
18
  *
11
- * See plugins/bizar/src/cline-runner.ts for the design rationale
12
- * and the structured-log wire format we parse.
19
+ * Background mode (--bg) keeps the agent alive in a daemon process.
20
+ * The output is monitored via the SDK (query() streams events) — for
21
+ * the dashboard's HTTP layer we just need: spawn, list, kill, status.
13
22
  */
23
+
14
24
  import { spawn } from 'node:child_process';
15
25
  import { createWriteStream, mkdirSync, existsSync } from 'node:fs';
16
26
  import { dirname } from 'node:path';
@@ -29,12 +39,13 @@ import { dirname } from 'node:path';
29
39
  *
30
40
  * @typedef {Object} SpawnAgentOptions
31
41
  * @property {string} prompt
32
- * @property {string} agent
33
- * @property {{ providerID: string, modelID: string }} [model]
42
+ * @property {string} [agent] subagent name from .claude/agents/
43
+ * @property {string} [model] sonnet | opus | haiku | provider/model
34
44
  * @property {string} worktree
35
45
  * @property {string} logPath
36
46
  * @property {string} [title]
37
47
  * @property {Object<string,string>} [env]
48
+ * @property {boolean} [background] if true, run via `claude --bg` (persistent)
38
49
  * @property {number} [sessionIdTimeoutMs]
39
50
  *
40
51
  * @typedef {Object} SpawnAgentResult
@@ -48,8 +59,8 @@ import { dirname } from 'node:path';
48
59
  const agents = new Map();
49
60
 
50
61
  /**
51
- * Spawn a single `cline run` process. Resolves once the cline
52
- * child has reported its session id in the structured log stream
62
+ * Spawn a single `claude` (or `claude --bg`) process. Resolves once
63
+ * the child has reported its session id in the JSON output stream
53
64
  * (or once the process exits before that).
54
65
  *
55
66
  * @param {SpawnAgentOptions} opts
@@ -69,30 +80,32 @@ export function spawnAgent(opts) {
69
80
  }
70
81
  }
71
82
 
72
- // 2. Build argv.
73
- const args = [
74
- 'run',
75
- '--dir', opts.worktree,
76
- '--print-logs',
77
- '--log-level', 'INFO',
78
- '--title', opts.title || `bgr:${opts.agent}:${Date.now()}`,
79
- ];
80
- if (opts.model) {
81
- args.push('--model', `${opts.model.providerID}/${opts.model.modelID}`);
82
- }
83
- args.push('--', opts.prompt);
83
+ // 2. Build argv. `claude --bg` keeps the session alive as a daemon;
84
+ // `claude -p` runs to completion and exits.
85
+ const args = [];
86
+ if (opts.background) args.push('--bg');
87
+ else args.push('-p', opts.prompt);
88
+
89
+ args.push('--output-format', 'json');
90
+ args.push('--verbose');
91
+ args.push('--add-dir', opts.worktree);
92
+ if (opts.title) args.push('--session-title', opts.title);
93
+ if (opts.agent) args.push('--agent', opts.agent);
94
+ if (opts.model) args.push('--model', opts.model);
84
95
 
85
- // 3. Spawn the process.
96
+ // 3. Spawn the process. Prefer the `claude` binary on PATH; fall
97
+ // back to `npx @anthropic-ai/claude-agent-sdk/cli` if not found.
86
98
  let proc;
87
99
  try {
88
- proc = spawn('cline', args, {
100
+ proc = spawn('claude', args, {
101
+ cwd: opts.worktree,
89
102
  stdio: ['ignore', 'pipe', 'pipe'],
90
103
  env: { ...process.env, ...(opts.env || {}) },
91
104
  });
92
105
  } catch (err) {
93
106
  return Promise.resolve({
94
107
  ok: false,
95
- error: `failed to spawn cline run: ${err.message}`,
108
+ error: `failed to spawn claude: ${err.message}`,
96
109
  });
97
110
  }
98
111
 
@@ -107,7 +120,10 @@ export function spawnAgent(opts) {
107
120
 
108
121
  // 5. Pipe stdout+stderr to the log file.
109
122
  const logStream = createWriteStream(opts.logPath, { flags: 'a' });
110
- const sessionIdRegex = /message=created id=(ses_[A-Za-z0-9_]+)/;
123
+
124
+ // Claude Code prints session-id in the JSON-line stream as soon as
125
+ // the run starts. Pattern: {"type":"system","subtype":"init","session_id":"..."}
126
+ const sessionIdRegex = /"session_id"\s*:\s*"([A-Za-z0-9_-]{6,})"/;
111
127
  let sessionId;
112
128
 
113
129
  const resolveSpawnIfReady = (forceError) => {
@@ -123,15 +139,14 @@ export function spawnAgent(opts) {
123
139
  }
124
140
  };
125
141
 
126
- // 6. Stream readers — line-buffered by splitting on newlines. We
127
- // append a [stdout]/[stderr] prefix for human readability.
142
+ // 6. Stream readers — line-buffered by splitting on newlines.
128
143
  const attachLineReader = (stream, label) => {
129
144
  let buf = '';
130
145
  stream.setEncoding('utf8');
131
146
  stream.on('data', (chunk) => {
132
147
  const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
133
148
  logStream.write(`[${label}] ${text}`);
134
- if (label === 'stderr' && !sessionId) {
149
+ if (!sessionId) {
135
150
  buf += text;
136
151
  const m = buf.match(sessionIdRegex);
137
152
  if (m && m[1]) {
@@ -142,8 +157,7 @@ export function spawnAgent(opts) {
142
157
  }
143
158
  });
144
159
  stream.on('end', () => {
145
- // Final flush attempt.
146
- if (label === 'stderr' && !sessionId && buf) {
160
+ if (!sessionId && buf) {
147
161
  const m = buf.match(sessionIdRegex);
148
162
  if (m && m[1]) {
149
163
  sessionId = m[1];
@@ -171,11 +185,11 @@ export function spawnAgent(opts) {
171
185
  rec.status.state = 'done';
172
186
  } else {
173
187
  rec.status.state = 'failed';
174
- rec.status.error = rec.status.error || `cline run exited with code ${exitCode}`;
188
+ rec.status.error = rec.status.error || `claude exited with code ${exitCode}`;
175
189
  }
176
190
  }
177
191
  if (!sessionId) {
178
- resolveSpawnIfReady(rec.status.error || 'cline run exited before reporting session id');
192
+ resolveSpawnIfReady(rec.status.error || 'claude exited before reporting session id');
179
193
  }
180
194
  const cbs = rec.onExit.splice(0);
181
195
  for (const cb of cbs) {
@@ -199,7 +213,7 @@ export function spawnAgent(opts) {
199
213
  setTimeout(() => {
200
214
  if (!sessionId) {
201
215
  resolveSpawnIfReady(
202
- `cline run did not report a session id within ${sessionIdTimeoutMs}ms`,
216
+ `claude did not report a session id within ${sessionIdTimeoutMs}ms`,
203
217
  );
204
218
  }
205
219
  }, sessionIdTimeoutMs);
@@ -208,8 +222,6 @@ export function spawnAgent(opts) {
208
222
 
209
223
  /**
210
224
  * Snapshot the current status of an agent.
211
- * @param {number} processId
212
- * @returns {AgentStatus | null}
213
225
  */
214
226
  export function getStatus(processId) {
215
227
  const rec = agents.get(processId);
@@ -218,11 +230,8 @@ export function getStatus(processId) {
218
230
  }
219
231
 
220
232
  /**
221
- * Subscribe to the exit event. Callback fires exactly once when
222
- * the process exits.
223
- * @param {number} processId
224
- * @param {(status: AgentStatus) => void} cb
225
- * @returns {() => void} unsubscribe
233
+ * Subscribe to the exit event. Callback fires exactly once when the
234
+ * process exits.
226
235
  */
227
236
  export function onExit(processId, cb) {
228
237
  const rec = agents.get(processId);
@@ -241,9 +250,6 @@ export function onExit(processId, cb) {
241
250
 
242
251
  /**
243
252
  * Kill the agent. Sends SIGTERM, waits up to 5s, then SIGKILL.
244
- * @param {number} processId
245
- * @param {'SIGTERM'|'SIGKILL'} [signal]
246
- * @returns {{ ok: boolean, error?: string }}
247
253
  */
248
254
  export function killAgent(processId, signal = 'SIGTERM') {
249
255
  const rec = agents.get(processId);
@@ -267,7 +273,6 @@ export function killAgent(processId, signal = 'SIGTERM') {
267
273
 
268
274
  /**
269
275
  * List every tracked agent.
270
- * @returns {AgentStatus[]}
271
276
  */
272
277
  export function list() {
273
278
  return Array.from(agents.values()).map((r) => ({ ...r.status }));
@@ -276,4 +281,4 @@ export function list() {
276
281
  /** For tests: clear the in-memory registry. */
277
282
  export function _resetForTests() {
278
283
  agents.clear();
279
- }
284
+ }