chorus-codes 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (293) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/cache/.previewinfo +1 -1
  4. package/.next/cache/.rscinfo +1 -1
  5. package/.next/cache/.tsbuildinfo +1 -1
  6. package/.next/fallback-build-manifest.json +3 -3
  7. package/.next/prerender-manifest.json +3 -3
  8. package/.next/server/app/_global-error.html +1 -1
  9. package/.next/server/app/_global-error.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.html +1 -1
  16. package/.next/server/app/_not-found.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/server/app/new.html +1 -1
  24. package/.next/server/app/new.rsc +1 -1
  25. package/.next/server/app/new.segments/_full.segment.rsc +1 -1
  26. package/.next/server/app/new.segments/_head.segment.rsc +1 -1
  27. package/.next/server/app/new.segments/_index.segment.rsc +1 -1
  28. package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
  29. package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +1 -1
  30. package/.next/server/app/new.segments/new.segment.rsc +1 -1
  31. package/.next/server/app/onboarding.html +1 -1
  32. package/.next/server/app/onboarding.rsc +1 -1
  33. package/.next/server/app/onboarding.segments/_full.segment.rsc +1 -1
  34. package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
  35. package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
  36. package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
  37. package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
  38. package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
  39. package/.next/server/app/personas.html +1 -1
  40. package/.next/server/app/personas.rsc +1 -1
  41. package/.next/server/app/personas.segments/_full.segment.rsc +1 -1
  42. package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
  43. package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
  44. package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
  45. package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +1 -1
  46. package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
  47. package/.next/server/app/settings.html +1 -1
  48. package/.next/server/app/settings.rsc +1 -1
  49. package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  50. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  51. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  52. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  53. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  54. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  55. package/.next/server/app/templates.html +1 -1
  56. package/.next/server/app/templates.rsc +1 -1
  57. package/.next/server/app/templates.segments/_full.segment.rsc +1 -1
  58. package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
  59. package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
  60. package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
  61. package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +1 -1
  62. package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
  63. package/.next/server/middleware-build-manifest.js +3 -3
  64. package/.next/server/pages/404.html +1 -1
  65. package/.next/server/pages/500.html +1 -1
  66. package/.next/server/server-reference-manifest.js +1 -1
  67. package/.next/server/server-reference-manifest.json +1 -1
  68. package/.next/trace +1 -1
  69. package/.next/trace-build +1 -1
  70. package/README.md +38 -15
  71. package/dist/cli/commands/doctor.js +116 -0
  72. package/dist/cli/commands/doctor.js.map +1 -0
  73. package/dist/cli/commands/init.js +211 -0
  74. package/dist/cli/commands/init.js.map +1 -0
  75. package/dist/cli/commands/start.js +298 -0
  76. package/dist/cli/commands/start.js.map +1 -0
  77. package/dist/cli/commands/status.js +54 -0
  78. package/dist/cli/commands/status.js.map +1 -0
  79. package/dist/cli/commands/stop.js +97 -0
  80. package/dist/cli/commands/stop.js.map +1 -0
  81. package/dist/cli/connect.js +108 -0
  82. package/dist/cli/connect.js.map +1 -0
  83. package/dist/cli/index.js +99 -0
  84. package/dist/cli/index.js.map +1 -0
  85. package/dist/cli/port-utils.js +260 -0
  86. package/dist/cli/port-utils.js.map +1 -0
  87. package/dist/cli/runtime-env.js +60 -0
  88. package/dist/cli/runtime-env.js.map +1 -0
  89. package/dist/cli/shared.js +54 -0
  90. package/dist/cli/shared.js.map +1 -0
  91. package/dist/cli/ui.js +60 -0
  92. package/dist/cli/ui.js.map +1 -0
  93. package/dist/daemon/agents/claude.js +98 -0
  94. package/dist/daemon/agents/claude.js.map +1 -0
  95. package/dist/daemon/agents/codex.js +160 -0
  96. package/dist/daemon/agents/codex.js.map +1 -0
  97. package/dist/daemon/agents/gemini.js +111 -0
  98. package/dist/daemon/agents/gemini.js.map +1 -0
  99. package/dist/daemon/agents/index.js +59 -0
  100. package/dist/daemon/agents/index.js.map +1 -0
  101. package/dist/daemon/agents/kimi.js +206 -0
  102. package/dist/daemon/agents/kimi.js.map +1 -0
  103. package/dist/daemon/agents/opencode.js +228 -0
  104. package/dist/daemon/agents/opencode.js.map +1 -0
  105. package/dist/daemon/agents/openrouter.js +274 -0
  106. package/dist/daemon/agents/openrouter.js.map +1 -0
  107. package/dist/daemon/agents/parsers/claude.js +63 -0
  108. package/dist/daemon/agents/parsers/claude.js.map +1 -0
  109. package/dist/daemon/agents/parsers/codex.js +51 -0
  110. package/dist/daemon/agents/parsers/codex.js.map +1 -0
  111. package/dist/daemon/agents/parsers/gemini.js +144 -0
  112. package/dist/daemon/agents/parsers/gemini.js.map +1 -0
  113. package/dist/daemon/agents/parsers/index.js +31 -0
  114. package/dist/daemon/agents/parsers/index.js.map +1 -0
  115. package/dist/daemon/agents/parsers/kimi.js +8 -0
  116. package/dist/daemon/agents/parsers/kimi.js.map +1 -0
  117. package/dist/daemon/agents/parsers/opencode.js +105 -0
  118. package/dist/daemon/agents/parsers/opencode.js.map +1 -0
  119. package/dist/daemon/agents/parsers/openrouter.js +69 -0
  120. package/dist/daemon/agents/parsers/openrouter.js.map +1 -0
  121. package/dist/daemon/agents/parsers/shared.js +17 -0
  122. package/dist/daemon/agents/parsers/shared.js.map +1 -0
  123. package/dist/daemon/agents/preflight.js +83 -0
  124. package/dist/daemon/agents/preflight.js.map +1 -0
  125. package/dist/daemon/agents/quote.js +45 -0
  126. package/dist/daemon/agents/quote.js.map +1 -0
  127. package/dist/daemon/agents/sandbox-guard.js +69 -0
  128. package/dist/daemon/agents/sandbox-guard.js.map +1 -0
  129. package/dist/daemon/agents/types.js +6 -0
  130. package/dist/daemon/agents/types.js.map +1 -0
  131. package/dist/daemon/api-response.js +65 -0
  132. package/dist/daemon/api-response.js.map +1 -0
  133. package/dist/daemon/error-detector.js +329 -0
  134. package/dist/daemon/error-detector.js.map +1 -0
  135. package/dist/daemon/headless.js +533 -0
  136. package/dist/daemon/headless.js.map +1 -0
  137. package/dist/daemon/index.js +333 -0
  138. package/dist/daemon/index.js.map +1 -0
  139. package/dist/daemon/openrouter.js +192 -0
  140. package/dist/daemon/openrouter.js.map +1 -0
  141. package/dist/daemon/orchestrators/claude.js +163 -0
  142. package/dist/daemon/orchestrators/claude.js.map +1 -0
  143. package/dist/daemon/orchestrators/codex.js +101 -0
  144. package/dist/daemon/orchestrators/codex.js.map +1 -0
  145. package/dist/daemon/orchestrators/cursor-windsurf.js +118 -0
  146. package/dist/daemon/orchestrators/cursor-windsurf.js.map +1 -0
  147. package/dist/daemon/orchestrators/gemini.js +108 -0
  148. package/dist/daemon/orchestrators/gemini.js.map +1 -0
  149. package/dist/daemon/orchestrators/index.js +90 -0
  150. package/dist/daemon/orchestrators/index.js.map +1 -0
  151. package/dist/daemon/orchestrators/kimi.js +108 -0
  152. package/dist/daemon/orchestrators/kimi.js.map +1 -0
  153. package/dist/daemon/orchestrators/opencode.js +152 -0
  154. package/dist/daemon/orchestrators/opencode.js.map +1 -0
  155. package/dist/daemon/orchestrators/shared.js +60 -0
  156. package/dist/daemon/orchestrators/shared.js.map +1 -0
  157. package/dist/daemon/output-watcher.js +131 -0
  158. package/dist/daemon/output-watcher.js.map +1 -0
  159. package/dist/daemon/participant-aborts.js +123 -0
  160. package/dist/daemon/participant-aborts.js.map +1 -0
  161. package/dist/daemon/reaper.js +46 -0
  162. package/dist/daemon/reaper.js.map +1 -0
  163. package/dist/daemon/routes/chats-events.js +62 -0
  164. package/dist/daemon/routes/chats-events.js.map +1 -0
  165. package/dist/daemon/routes/chats-stream.js +241 -0
  166. package/dist/daemon/routes/chats-stream.js.map +1 -0
  167. package/dist/daemon/routes/chats-validation.js +13 -0
  168. package/dist/daemon/routes/chats-validation.js.map +1 -0
  169. package/dist/daemon/routes/chats.js +545 -0
  170. package/dist/daemon/routes/chats.js.map +1 -0
  171. package/dist/daemon/routes/openrouter.js +103 -0
  172. package/dist/daemon/routes/openrouter.js.map +1 -0
  173. package/dist/daemon/routes/settings.js +199 -0
  174. package/dist/daemon/routes/settings.js.map +1 -0
  175. package/dist/daemon/routes/stats.js +155 -0
  176. package/dist/daemon/routes/stats.js.map +1 -0
  177. package/dist/daemon/routes/system.js +208 -0
  178. package/dist/daemon/routes/system.js.map +1 -0
  179. package/dist/daemon/routes/templates-personas.js +254 -0
  180. package/dist/daemon/routes/templates-personas.js.map +1 -0
  181. package/dist/daemon/routes/voices.js +139 -0
  182. package/dist/daemon/routes/voices.js.map +1 -0
  183. package/dist/daemon/runner/doer-driver.js +346 -0
  184. package/dist/daemon/runner/doer-driver.js.map +1 -0
  185. package/dist/daemon/runner/doer.js +336 -0
  186. package/dist/daemon/runner/doer.js.map +1 -0
  187. package/dist/daemon/runner/prior-round.js +140 -0
  188. package/dist/daemon/runner/prior-round.js.map +1 -0
  189. package/dist/daemon/runner/prompt-builder.js +292 -0
  190. package/dist/daemon/runner/prompt-builder.js.map +1 -0
  191. package/dist/daemon/runner/review-only-phase.js +103 -0
  192. package/dist/daemon/runner/review-only-phase.js.map +1 -0
  193. package/dist/daemon/runner/reviewer-driver.js +410 -0
  194. package/dist/daemon/runner/reviewer-driver.js.map +1 -0
  195. package/dist/daemon/runner/reviewer.js +384 -0
  196. package/dist/daemon/runner/reviewer.js.map +1 -0
  197. package/dist/daemon/runner/run-with-fallback.js +56 -0
  198. package/dist/daemon/runner/run-with-fallback.js.map +1 -0
  199. package/dist/daemon/runner/sanitize-name.js +8 -0
  200. package/dist/daemon/runner/sanitize-name.js.map +1 -0
  201. package/dist/daemon/runner/stream-file-writer.js +116 -0
  202. package/dist/daemon/runner/stream-file-writer.js.map +1 -0
  203. package/dist/daemon/runner/swap-sidecar.js +102 -0
  204. package/dist/daemon/runner/swap-sidecar.js.map +1 -0
  205. package/dist/daemon/runner/template-fallback.js +119 -0
  206. package/dist/daemon/runner/template-fallback.js.map +1 -0
  207. package/dist/daemon/runner/types.js +3 -0
  208. package/dist/daemon/runner/types.js.map +1 -0
  209. package/dist/daemon/runner/verdict.js +51 -0
  210. package/dist/daemon/runner/verdict.js.map +1 -0
  211. package/dist/daemon/runner-multiplex.js +364 -0
  212. package/dist/daemon/runner-multiplex.js.map +1 -0
  213. package/dist/daemon/runner.js +427 -0
  214. package/dist/daemon/runner.js.map +1 -0
  215. package/dist/daemon/ship.js +340 -0
  216. package/dist/daemon/ship.js.map +1 -0
  217. package/dist/daemon/template-cache.js +37 -0
  218. package/dist/daemon/template-cache.js.map +1 -0
  219. package/dist/daemon/tmux-types.js +9 -0
  220. package/dist/daemon/tmux-types.js.map +1 -0
  221. package/dist/daemon/tmux.js +341 -0
  222. package/dist/daemon/tmux.js.map +1 -0
  223. package/dist/lib/atomic-write.js +55 -0
  224. package/dist/lib/atomic-write.js.map +1 -0
  225. package/dist/lib/chat-events-bus.js +27 -0
  226. package/dist/lib/chat-events-bus.js.map +1 -0
  227. package/dist/lib/chat-slug.js +105 -0
  228. package/dist/lib/chat-slug.js.map +1 -0
  229. package/dist/lib/cli-detect.js +388 -0
  230. package/dist/lib/cli-detect.js.map +1 -0
  231. package/dist/lib/cli-health.js +156 -0
  232. package/dist/lib/cli-health.js.map +1 -0
  233. package/dist/lib/cli-paths.js +113 -0
  234. package/dist/lib/cli-paths.js.map +1 -0
  235. package/dist/lib/cli-precheck.js +141 -0
  236. package/dist/lib/cli-precheck.js.map +1 -0
  237. package/dist/lib/db/chats.js +244 -0
  238. package/dist/lib/db/chats.js.map +1 -0
  239. package/dist/lib/db/connection.js +254 -0
  240. package/dist/lib/db/connection.js.map +1 -0
  241. package/dist/lib/db/index.js +34 -0
  242. package/dist/lib/db/index.js.map +1 -0
  243. package/dist/lib/db/personas.js +65 -0
  244. package/dist/lib/db/personas.js.map +1 -0
  245. package/dist/lib/db/phase-events.js +172 -0
  246. package/dist/lib/db/phase-events.js.map +1 -0
  247. package/dist/lib/db/secrets.js +53 -0
  248. package/dist/lib/db/secrets.js.map +1 -0
  249. package/dist/lib/db/settings.js +47 -0
  250. package/dist/lib/db/settings.js.map +1 -0
  251. package/dist/lib/db/templates.js +75 -0
  252. package/dist/lib/db/templates.js.map +1 -0
  253. package/dist/lib/db/voices.js +184 -0
  254. package/dist/lib/db/voices.js.map +1 -0
  255. package/dist/lib/lineage-maps.js +200 -0
  256. package/dist/lib/lineage-maps.js.map +1 -0
  257. package/dist/lib/logger.js +186 -0
  258. package/dist/lib/logger.js.map +1 -0
  259. package/dist/lib/personas.js +117 -0
  260. package/dist/lib/personas.js.map +1 -0
  261. package/dist/lib/runtime-path.js +222 -0
  262. package/dist/lib/runtime-path.js.map +1 -0
  263. package/dist/lib/settings/billing.js +58 -0
  264. package/dist/lib/settings/billing.js.map +1 -0
  265. package/dist/lib/settings/permissions.js +81 -0
  266. package/dist/lib/settings/permissions.js.map +1 -0
  267. package/dist/lib/settings/transport.js +113 -0
  268. package/dist/lib/settings/transport.js.map +1 -0
  269. package/dist/lib/telemetry.js +290 -0
  270. package/dist/lib/telemetry.js.map +1 -0
  271. package/dist/lib/template-schema.js +319 -0
  272. package/dist/lib/template-schema.js.map +1 -0
  273. package/dist/lib/template-validation.js +82 -0
  274. package/dist/lib/template-validation.js.map +1 -0
  275. package/dist/lib/voices.js +533 -0
  276. package/dist/lib/voices.js.map +1 -0
  277. package/dist/mcp/client.js +138 -0
  278. package/dist/mcp/client.js.map +1 -0
  279. package/dist/mcp/index.js +178 -0
  280. package/dist/mcp/index.js.map +1 -0
  281. package/dist/mcp/tools.js +355 -0
  282. package/dist/mcp/tools.js.map +1 -0
  283. package/package.json +2 -1
  284. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js +0 -6077
  285. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js.map +0 -69
  286. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js +0 -6318
  287. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js.map +0 -71
  288. package/.next/dev/types/cache-life.d.ts +0 -145
  289. package/.next/dev/types/routes.d.ts +0 -84
  290. package/.next/dev/types/validator.ts +0 -178
  291. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_buildManifest.js +0 -0
  292. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_clientMiddlewareManifest.js +0 -0
  293. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_ssgManifest.js +0 -0
@@ -0,0 +1,329 @@
1
+ "use strict";
2
+ /**
3
+ * CLI Failure Detector
4
+ *
5
+ * Pattern-matches tmux pane snapshots to detect known failure modes from
6
+ * codex/claude/gemini/opencode CLIs. Returns structured CliError events
7
+ * the runner emits as `cli_error` SSE messages.
8
+ *
9
+ * Observed patterns documented in:
10
+ * /home/ubuntu/.claude/projects/-home-ubuntu/memory/chorus_cli_failure_modes.md
11
+ * /home/ubuntu/.claude/projects/-home-ubuntu/memory/feedback_opencode_session_db_corruption.md
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.ErrorDetector = void 0;
15
+ /**
16
+ * Parse human-readable reset time like "Apr 30th, 2026 10:05 PM" to ms-epoch.
17
+ * Returns undefined on parse failure (UI hides the timer in that case).
18
+ */
19
+ function parseResetTime(humanTime) {
20
+ if (!humanTime)
21
+ return undefined;
22
+ // Strip ordinal suffixes: "1st" → "1", "2nd" → "2", "3rd" → "3", "4th" → "4", etc.
23
+ const cleaned = humanTime.replace(/(\d+)(st|nd|rd|th)\b/gi, '$1');
24
+ const t = Date.parse(cleaned);
25
+ return Number.isFinite(t) ? t : undefined;
26
+ }
27
+ /**
28
+ * ErrorDetector — stateful pattern-matching for CLI failure modes.
29
+ *
30
+ * Patterns 1-3 (quota, token-refresh, MCP) are stateless — matched inline.
31
+ * Pattern 4 (opencode DB corruption) is stateful — tracks error frequency.
32
+ *
33
+ * Per-session dedup: the runner polls capture-pane every ~2s, so the same
34
+ * quota text sits in the buffer and would emit on every poll. We track the
35
+ * last-emitted error kind per session and suppress repeats of the same kind
36
+ * until a different kind (or no error) appears.
37
+ */
38
+ class ErrorDetector {
39
+ openCodeState = new Map();
40
+ lastEmittedKind = new Map();
41
+ /**
42
+ * Inspect a tmux pane snapshot for known failure patterns.
43
+ * Returns a CliError if a pattern matched, null otherwise.
44
+ *
45
+ * For opencode_db_corrupt: tracks state internally. Call reset() when
46
+ * the session is killed or restarted to clear per-session counters.
47
+ */
48
+ inspect(sessionName, lineage, paneText) {
49
+ const result = this.detect(sessionName, lineage, paneText);
50
+ if (!result) {
51
+ // No error currently visible — clear dedup so a recurring kind
52
+ // (e.g. a *second* permission_prompt after we recovered the first) can
53
+ // re-fire later. Without this, recoverable+recurring events are silently
54
+ // suppressed for the rest of the session.
55
+ this.lastEmittedKind.delete(sessionName);
56
+ return null;
57
+ }
58
+ // Dedup: skip if we already emitted this exact kind for this session.
59
+ // The user's experience: one quota error event per quota event, not 149.
60
+ const lastKind = this.lastEmittedKind.get(sessionName);
61
+ if (lastKind === result.kind)
62
+ return null;
63
+ this.lastEmittedKind.set(sessionName, result.kind);
64
+ return result;
65
+ }
66
+ /** Inner pattern matcher — see inspect() for the dedup wrapper. */
67
+ detect(sessionName, lineage, paneText) {
68
+ // Pattern 1: Codex quota exhausted
69
+ if (lineage === 'openai') {
70
+ const quotaMatch = /You've hit your usage limit\.[\s\S]*?try again at\s+([^\n.]+)/i.exec(paneText);
71
+ if (quotaMatch) {
72
+ const resetAtStr = quotaMatch[1];
73
+ return {
74
+ kind: 'quota_exhausted',
75
+ lineage,
76
+ message: resetAtStr
77
+ ? `Codex quota exhausted. Resets ${resetAtStr.trim()}.`
78
+ : 'Codex quota exhausted.',
79
+ cta: 'Switch to a different codex account, or wait & retry.',
80
+ resetAt: parseResetTime(resetAtStr),
81
+ detail: quotaMatch[0],
82
+ };
83
+ }
84
+ // Pattern 2: Codex token refresh lost
85
+ if (/access token could not be refreshed/i.test(paneText)) {
86
+ const match = /access token could not be refreshed[^\n]*/i.exec(paneText);
87
+ return {
88
+ kind: 'token_refresh_lost',
89
+ lineage,
90
+ message: 'Codex auth invalidated (token refresh race).',
91
+ cta: 'Re-authenticate codex.',
92
+ detail: match?.[0],
93
+ };
94
+ }
95
+ // Pattern 3: Codex MCP handshake failed
96
+ if (/handshaking with MCP server failed/i.test(paneText)) {
97
+ const match = /handshaking with MCP server failed[^\n]*/i.exec(paneText);
98
+ return {
99
+ kind: 'mcp_handshake_failed',
100
+ lineage,
101
+ message: 'Codex MCP startup failed.',
102
+ cta: 'Re-authenticate codex.',
103
+ detail: match?.[0],
104
+ };
105
+ }
106
+ }
107
+ // Pattern 1b: Anthropic Claude usage limit (Pro/Max subscriptions
108
+ // have rolling 5-hour message caps). Phrasing covers both the
109
+ // older "Claude usage limit reached" and the explicit reset variant.
110
+ if (lineage === 'anthropic') {
111
+ const claudeQuota = /(?:Claude (?:AI )?usage limit reached|5-hour (?:message|usage) limit|message limit reached)[\s\S]*?(?:reset|try again)\s*(?:at)?\s*([^\n.]+)?/i.exec(paneText);
112
+ if (claudeQuota) {
113
+ const reset = claudeQuota[1]?.trim();
114
+ return {
115
+ kind: 'quota_exhausted',
116
+ lineage,
117
+ message: reset
118
+ ? `Claude usage limit reached. Resets ${reset}.`
119
+ : 'Claude usage limit reached.',
120
+ cta: 'Switch to a different Claude account, or wait for reset.',
121
+ resetAt: parseResetTime(reset),
122
+ detail: claudeQuota[0].slice(0, 200),
123
+ };
124
+ }
125
+ }
126
+ // Pattern 1c: Gemini RESOURCE_EXHAUSTED — the Google API's standard
127
+ // quota signal across the free tier and paid tiers. Surfaces in the
128
+ // Gemini CLI as either the raw code or the friendlier "Quota exceeded".
129
+ if (lineage === 'google') {
130
+ const geminiQuota = /(RESOURCE_EXHAUSTED|429.*Quota exceeded|Quota exceeded for quota metric|"code"\s*:\s*429)/i.exec(paneText);
131
+ if (geminiQuota) {
132
+ return {
133
+ kind: 'quota_exhausted',
134
+ lineage,
135
+ message: 'Gemini quota exhausted (free-tier or daily cap).',
136
+ cta: 'Wait for the daily reset, switch projects, or use a different model.',
137
+ detail: geminiQuota[0].slice(0, 200),
138
+ };
139
+ }
140
+ // ModelNotFoundError — bad model id (e.g. user picked a model that
141
+ // got deprecated). Surface as auth_invalid-equivalent so the run
142
+ // card shows a clear CTA rather than silent 0-byte answer.md.
143
+ if (/ModelNotFoundError|404\s*Not Found.*model/i.test(paneText)) {
144
+ return {
145
+ kind: 'mcp_handshake_failed', // reuses auth_invalid status mapping
146
+ lineage,
147
+ message: 'Gemini rejected the requested model id.',
148
+ cta: 'Pick a different Gemini model on the Connect page.',
149
+ };
150
+ }
151
+ }
152
+ // Pattern 1d: OpenCode-Go subscription out of credits. opencode-go's
153
+ // `/usage` endpoint returns "Out of credits" / "subscription quota
154
+ // exceeded"; the TUI surfaces the same string. Distinct from
155
+ // opencode_db_corrupt (Pattern 4) which is a session-replay failure.
156
+ if (lineage === 'opencode') {
157
+ if (/subscription quota exceeded|Out of credits|insufficient credits/i.test(paneText)) {
158
+ return {
159
+ kind: 'quota_exhausted',
160
+ lineage,
161
+ message: 'OpenCode subscription is out of credits.',
162
+ cta: 'Top up at opencode.ai/billing or switch to a different model.',
163
+ detail: 'opencode-go subscription quota signal in pane.',
164
+ };
165
+ }
166
+ }
167
+ // Pattern 1e: Generic "please log in" auth signal across every
168
+ // interactive CLI we drive. Catches the common phrasings:
169
+ // - claude: "Please run `claude login`"
170
+ // - codex: "Run `codex login` to sign in"
171
+ // - gemini: "Authentication required" / "gcloud auth"
172
+ // - opencode: "opencode auth login"
173
+ // - kimi: "kimi: not logged in"
174
+ // Done after the per-CLI patterns above so the more-specific
175
+ // detectors (token_refresh_lost, mcp_handshake_failed) take priority.
176
+ if (lineage === 'anthropic' ||
177
+ lineage === 'openai' ||
178
+ lineage === 'google' ||
179
+ lineage === 'opencode' ||
180
+ lineage === 'moonshot') {
181
+ const authPrompt = /(?:please (?:run|log\s*in|sign\s*in)|run\s+`?(?:claude|codex|gemini|opencode|kimi)\s+login|to\s+sign\s+in|not logged in|not authenticated|no active session|authentication required|api key (?:invalid|missing|expired|revoked))/i.exec(paneText);
182
+ if (authPrompt) {
183
+ return {
184
+ kind: 'token_refresh_lost', // maps to auth_invalid health status
185
+ lineage,
186
+ message: `${lineage} CLI is asking you to re-authenticate.`,
187
+ cta: 'Re-run the CLI login (e.g. `claude login`, `codex login`, `gemini` interactive setup).',
188
+ detail: authPrompt[0].slice(0, 200),
189
+ };
190
+ }
191
+ }
192
+ // Pattern 4: Opencode DB corruption (stateful)
193
+ // Accept both 'opencode' (current) and 'xai' (legacy alias) lineage tags
194
+ // so older templates / sessions don't silently lose detection.
195
+ //
196
+ // NOTE: must NOT short-circuit when corruption isn't found — the original
197
+ // code returned the corruption result unconditionally and silently masked
198
+ // the permission_prompt detection (Pattern 5) for the entire opencode
199
+ // family. Fall through on null so the dialog detector below can still run.
200
+ if (lineage === 'opencode' || lineage === 'xai') {
201
+ const corruption = this.inspectOpenCodeCorruption(sessionName, paneText);
202
+ if (corruption)
203
+ return corruption;
204
+ }
205
+ // Pattern 5: Permission prompt — lineage-agnostic.
206
+ //
207
+ // Catches "Always allow" / "Allow this tool?" / approval dialogs across
208
+ // every CLI we drive (opencode, kimi, claude, codex, gemini). Layer 1 of
209
+ // the permission model (config-file pre-approval) makes this rare; this
210
+ // pattern is Layer 2 — defense-in-depth. The runner consults the shim's
211
+ // `recoverKeys.permission_prompt` to navigate the dialog (e.g. opencode
212
+ // needs `['Right', 'Enter']` to pick "Always allow") and emits a
213
+ // `cli_warning` rather than failing the chat.
214
+ //
215
+ // Filtered to interactive CLIs only — sentinel like 'any' has no UI.
216
+ const isInteractiveCli = lineage === 'anthropic' ||
217
+ lineage === 'openai' ||
218
+ lineage === 'google' ||
219
+ lineage === 'opencode' ||
220
+ lineage === 'moonshot';
221
+ if (isInteractiveCli) {
222
+ // Lineage-aware matching:
223
+ //
224
+ // opencode/xai (and moonshot/kimi-standalone, same upstream code):
225
+ // OpenCode 1.14.x's permission UI is a TWO-STEP dialog. Step 1 has
226
+ // three buttons in a row ("Allow once Allow always Reject");
227
+ // step 2 is a nested confirm ("△ Always allow … Confirm Cancel").
228
+ // Tight regex pinned to the step-1 button row prevents the detector
229
+ // from re-firing on step 2's "Always allow" heading. That's load-
230
+ // bearing: the shim's recoverKeys sends `[Right, Enter, Enter]` to
231
+ // clear BOTH dialogs in one shot; if step 2 also matched here and
232
+ // a recovery fired against it, `Right` would move the highlight
233
+ // "Confirm" → "Cancel" and `Enter` would REJECT the command. The
234
+ // dedup guard at the inspect() layer mostly hides this hazard, but
235
+ // a single buffer-redraw window where step-2 matches alone can
236
+ // re-arm it. Solving it at the regex level removes the failure
237
+ // mode entirely instead of relying on dedup timing.
238
+ //
239
+ // anthropic/openai/google:
240
+ // Generic phrasings — Claude's "Approve and run", Codex's "Approve
241
+ // this call", Gemini's "[a]llow" / "Always allow". Broad regex
242
+ // keeps the existing coverage; these CLIs don't have the nested-
243
+ // confirm hazard.
244
+ //
245
+ // Both sub-patterns refuse to match free-form chat content like
246
+ // "approve this PR" by anchoring on TUI markers (the △ glyph, the
247
+ // bracketed letter, or the multi-button row layout).
248
+ const isOpenCodeFamily = lineage === 'opencode' || lineage === 'moonshot';
249
+ const promptMatch = isOpenCodeFamily
250
+ ? /Allow once\s+(?:Always allow|Allow always)\s+Reject/i.exec(paneText)
251
+ : /(\b|△ ?)(Always allow|Allow always|Allow this|Allow once|Approve this call|Approve and run|\[a\]llow)\b/i.exec(paneText);
252
+ if (promptMatch) {
253
+ return {
254
+ kind: 'permission_prompt',
255
+ lineage,
256
+ message: `${lineage} is showing an approval dialog.`,
257
+ cta: 'Runner auto-recovers via shim.recoverKeys; if missing, click "Always allow" manually.',
258
+ detail: promptMatch[0],
259
+ };
260
+ }
261
+ }
262
+ return null;
263
+ }
264
+ /**
265
+ * Stateful opencode detector: tracks "Provider returned error" frequency.
266
+ *
267
+ * Rules:
268
+ * - Increment errCount if "Provider returned error" appears
269
+ * - Reset errCount to 0 if we see "## DONE" (successful completion)
270
+ * - Trigger opencode_db_corrupt when errCount >= 3 AND no success in last 60s
271
+ */
272
+ inspectOpenCodeCorruption(sessionName, paneText) {
273
+ // Initialize state if first call for this session
274
+ let state = this.openCodeState.get(sessionName);
275
+ if (!state) {
276
+ state = { errCount: 0, lastErrAt: 0, lastSuccessAt: Date.now() };
277
+ this.openCodeState.set(sessionName, state);
278
+ }
279
+ const now = Date.now();
280
+ // Check for successful completion sentinel
281
+ if (/## DONE\b/i.test(paneText)) {
282
+ state.errCount = 0;
283
+ state.lastSuccessAt = now;
284
+ return null;
285
+ }
286
+ // Count "Provider returned error" occurrences in this snapshot
287
+ const errorMatches = paneText.match(/Provider returned error/gi);
288
+ if (errorMatches) {
289
+ state.errCount += errorMatches.length;
290
+ state.lastErrAt = now;
291
+ }
292
+ // Trigger corruption error when:
293
+ // - errCount >= 3 (multiple repeated errors)
294
+ // - AND last success was >60 seconds ago (sustained failure, not transient)
295
+ if (state.errCount >= 3 && now - state.lastSuccessAt > 60000) {
296
+ return {
297
+ kind: 'opencode_db_corrupt',
298
+ lineage: 'opencode',
299
+ message: 'Opencode session DB likely corrupted (Kimi rejecting empty msgs).',
300
+ cta: 'Run `work-fleet-restart kimi deepseek` after wiping ~/.local/share/opencode/opencode.db',
301
+ detail: 'Multiple Provider-returned-error responses in window.',
302
+ };
303
+ }
304
+ return null;
305
+ }
306
+ /**
307
+ * Reset per-session state (call when a session is killed or restarted).
308
+ * Clears the error counter so a fresh retry doesn't auto-trigger on old errors.
309
+ */
310
+ reset(sessionName) {
311
+ this.openCodeState.delete(sessionName);
312
+ this.lastEmittedKind.delete(sessionName);
313
+ }
314
+ /**
315
+ * Periodic cleanup of stale state. Removes sessions idle >maxIdleMs.
316
+ * Call every 5 minutes from the reaper.
317
+ */
318
+ cleanup(maxIdleMs) {
319
+ const now = Date.now();
320
+ for (const [sessionName, state] of this.openCodeState.entries()) {
321
+ const lastActivity = Math.max(state.lastErrAt, state.lastSuccessAt);
322
+ if (now - lastActivity > maxIdleMs) {
323
+ this.openCodeState.delete(sessionName);
324
+ }
325
+ }
326
+ }
327
+ }
328
+ exports.ErrorDetector = ErrorDetector;
329
+ //# sourceMappingURL=error-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-detector.js","sourceRoot":"","sources":["../../src/daemon/error-detector.ts"],"names":[],"mappings":"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"}