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,206 @@
1
+ "use strict";
2
+ /**
3
+ * Kimi CLI (MoonshotAI) agent shim.
4
+ *
5
+ * Uses `--afk` flag which auto-dismisses AskUserQuestion AND auto-approves
6
+ * tool calls. Equivalent to claude's auto-accept and codex's
7
+ * approval_policy=never. Without it kimi shows a one-time "Allow this tool?"
8
+ * dialog that would block a chorus-spawned reviewer indefinitely.
9
+ *
10
+ * If a new kimi release ever drops `--afk`, the error-detector pattern in
11
+ * src/daemon/error-detector.ts (kind='permission_prompt') is a defense-in-
12
+ * depth fallback — runner can capture-pane and send-keys to dismiss it.
13
+ *
14
+ * MCP context: kimi spawned as a reviewer doesn't talk to chorus's own MCP
15
+ * server (that would be circular). It just reads ask.md, writes answer.md.
16
+ */
17
+ var __importDefault = (this && this.__importDefault) || function (mod) {
18
+ return (mod && mod.__esModule) ? mod : { "default": mod };
19
+ };
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.kimiShim = void 0;
22
+ const node_fs_1 = __importDefault(require("node:fs"));
23
+ const node_os_1 = __importDefault(require("node:os"));
24
+ const node_path_1 = __importDefault(require("node:path"));
25
+ const quote_js_1 = require("./quote.js");
26
+ const headless_js_1 = require("../headless.js");
27
+ const index_js_1 = require("./parsers/index.js");
28
+ const atomic_write_js_1 = require("../../lib/atomic-write.js");
29
+ const opencode_js_1 = require("./opencode.js");
30
+ const sandbox_guard_js_1 = require("./sandbox-guard.js");
31
+ let cachedTransport = null;
32
+ function detectKimiTransport() {
33
+ if (cachedTransport)
34
+ return cachedTransport;
35
+ const override = process.env.CHORUS_KIMI_TRANSPORT;
36
+ if (override === 'kimi-cli' || override === 'opencode') {
37
+ cachedTransport = override;
38
+ return override;
39
+ }
40
+ // Probe the standalone kimi config — non-empty `default_model` OR any
41
+ // `[models.<name>]` table means the user has wired up a real model.
42
+ const configPath = node_path_1.default.join(node_os_1.default.homedir(), '.kimi', 'config.toml');
43
+ if (node_fs_1.default.existsSync(configPath)) {
44
+ try {
45
+ const body = node_fs_1.default.readFileSync(configPath, 'utf-8');
46
+ const defaultModel = body.match(/^\s*default_model\s*=\s*["']([^"']+)["']/m);
47
+ const hasDefault = defaultModel != null && defaultModel[1].length > 0;
48
+ const hasModelsTable = /^\[models\.[A-Za-z0-9_.-]+\]/m.test(body);
49
+ if (hasDefault || hasModelsTable) {
50
+ cachedTransport = 'kimi-cli';
51
+ return 'kimi-cli';
52
+ }
53
+ }
54
+ catch {
55
+ /* fall through */
56
+ }
57
+ }
58
+ cachedTransport = 'opencode';
59
+ return 'opencode';
60
+ }
61
+ /**
62
+ * Drop a per-participant `_meta.json` sidecar so the cockpit can show
63
+ * which binary + model actually ran. Without this the run page would
64
+ * always say "kimi-cli · kimi-k2.6" even when the underlying transport
65
+ * is opencode + opencode-go/kimi-k2.6. Best-effort — failures are silent
66
+ * (the sidecar is purely informational).
67
+ */
68
+ function writeTransportMeta(cwd, binary, model) {
69
+ try {
70
+ // Atomic temp+rename — cockpit polls this file; a crash mid-write would
71
+ // otherwise leave a half-written JSON that the parser rejects. See
72
+ // src/lib/atomic-write.ts for the rationale.
73
+ const metaPath = node_path_1.default.join(cwd, '_meta.json');
74
+ (0, atomic_write_js_1.atomicWriteJsonSync)(metaPath, { binary, model, ts: Date.now() });
75
+ }
76
+ catch {
77
+ /* informational only */
78
+ }
79
+ }
80
+ exports.kimiShim = {
81
+ lineage: 'moonshot',
82
+ name: 'kimi-cli',
83
+ buildLaunchCommand(opts) {
84
+ (0, quote_js_1.validateValue)('model', opts.model);
85
+ // Same fail-closed gate as opencode — kimi-cli mirrors opencode's
86
+ // codebase and inherits the same gap. Audit D1 BLOCKER.
87
+ (0, sandbox_guard_js_1.assertSandboxSupported)(opts.sandbox, 'kimi');
88
+ const cwd = (0, quote_js_1.quotePath)(opts.cwd);
89
+ let cmd = `cd ${cwd} && kimi`;
90
+ // --afk auto-dismisses prompts and auto-approves tool calls. Default ON
91
+ // for headless reviewer spawns; user can flip via settings if they want
92
+ // to be prompted in the kimi terminal session.
93
+ if (opts.autoApprove !== false) {
94
+ cmd += ` --afk`;
95
+ }
96
+ if (opts.model) {
97
+ cmd += ` -m ${(0, quote_js_1.quoteValue)(opts.model)}`;
98
+ }
99
+ return cmd;
100
+ },
101
+ // Defense-in-depth recovery if --afk is dropped or a future kimi rev shows
102
+ // a different prompt shape. The kimi standalone CLI mirrors opencode's
103
+ // 2-step dialog UX (it's the same upstream codebase) so we send the same
104
+ // 3-key sequence: `Right` highlights "Allow always", first `Enter` opens
105
+ // the nested "Confirm/Cancel" dialog (default = Confirm), second `Enter`
106
+ // confirms it. See opencode.ts for the full per-key rationale.
107
+ recoverKeys: {
108
+ permission_prompt: ['Right', 'Enter', 'Enter'],
109
+ },
110
+ formatPrompt(opts) {
111
+ const sentinel = opts.expectDoneSentinel
112
+ ? '\n\nWhen finished, end your response with: ## DONE'
113
+ : '';
114
+ return (`${opts.task}\n\n` +
115
+ `Read the prompt at: ${opts.promptFile}\n\n` +
116
+ `Write your full answer to: ${opts.answerFile}${sentinel}`);
117
+ },
118
+ /**
119
+ * Headless mode — branches on detected transport (see top-of-file
120
+ * comment for the kimi-cli vs opencode-go decision tree).
121
+ *
122
+ * - kimi-cli: streaming `kimi --print --output-format stream-json`,
123
+ * parsed via parseKimi (Claude-Code-compatible JSON events).
124
+ *
125
+ * - opencode: one-shot `opencode run --format json --model
126
+ * opencode-go/kimi-k2.6 "<prompt>"`, parsed via parseOpencode
127
+ * (JSON-Lines, one text event per LLM message).
128
+ *
129
+ * Model normalisation: templates pass `kimi-k2.6` (plain). For the
130
+ * opencode path we prepend `opencode-go/` so the CLI routes through
131
+ * the Go subscription gateway.
132
+ */
133
+ runHeadless(opts) {
134
+ const sandboxError = (0, sandbox_guard_js_1.sandboxFailClosed)(opts.sandbox, 'kimi');
135
+ if (sandboxError)
136
+ return sandboxError;
137
+ const transport = detectKimiTransport();
138
+ if (transport === 'kimi-cli') {
139
+ const model = opts.model ?? 'kimi-k2.6';
140
+ writeTransportMeta(opts.cwd, 'kimi-cli', model);
141
+ const args = ['--print', '--output-format', 'stream-json'];
142
+ if (opts.model)
143
+ args.push('-m', opts.model);
144
+ const run = (0, headless_js_1.spawnHeadless)({
145
+ command: 'kimi',
146
+ args,
147
+ cwd: opts.cwd,
148
+ stdinPayload: opts.promptText,
149
+ parseLine: index_js_1.parseKimi,
150
+ // cli tag is the binary that actually ran — error messages quote
151
+ // it as "{cli} exited N", so misattributing failures to the wrong
152
+ // binary sends the user looking at the wrong PATH/auth/install.
153
+ cli: 'kimi',
154
+ timeoutMs: opts.timeoutMs,
155
+ abortSignal: opts.abortSignal,
156
+ heartbeat: false,
157
+ });
158
+ return run.events;
159
+ }
160
+ // opencode path — qualify the model with the opencode-go/ prefix.
161
+ const rawModel = opts.model ?? 'kimi-k2.6';
162
+ const model = rawModel.startsWith('opencode-go/')
163
+ ? rawModel
164
+ : `opencode-go/${rawModel}`;
165
+ writeTransportMeta(opts.cwd, 'opencode-cli', model);
166
+ // Argv-overflow guard: stash the prompt on disk and pass a tiny argv
167
+ // directive instead of the full prompt. Mirrors opencodeShim — see its
168
+ // runHeadless for why (opencode `run` only takes a positional argv).
169
+ const promptPath = node_path_1.default.join(opts.cwd, 'prompt.md');
170
+ node_fs_1.default.writeFileSync(promptPath, opts.promptText, 'utf-8');
171
+ const directive = `Open the file at this absolute path using your read tool: ${promptPath} ` +
172
+ `— follow the instructions inside exactly and respond with your full answer in this conversation, ending with ## DONE.`;
173
+ const opencodeArgs = ['run', '--format', 'json', '--model', model, directive];
174
+ // PTY-wrap the spawn — opencode 1.14.x's `run --format json` checks
175
+ // isatty(stdout) and emits zero bytes when piped (model still runs to
176
+ // completion, just no JSON output). The opencode shim's runHeadless
177
+ // wraps for the same reason. Without this, every Kimi reviewer routed
178
+ // through the opencode-go transport (the default when no standalone
179
+ // kimi config exists) silently produces 0-byte answer.md — exactly the
180
+ // failure mode the opencode PTY fix was written to prevent. Confirmed
181
+ // launch-eve by both deepseek and gemini reviewing the shims; the bug
182
+ // was a copy-paste oversight when the PTY fix landed in opencode.ts.
183
+ const { command, args } = (0, opencode_js_1.wrapWithPty)('opencode', opencodeArgs);
184
+ const run = (0, headless_js_1.spawnHeadless)({
185
+ command,
186
+ args,
187
+ cwd: opts.cwd,
188
+ parseLine: index_js_1.parseOpencode,
189
+ onExit: (fullStdout) => (0, index_js_1.parseOpencodeExit)(fullStdout),
190
+ // Tag the failure as 'opencode' — that's the binary that runs.
191
+ // The previous 'kimi' tag emitted "kimi exited 127: opencode:
192
+ // command not found" which sent the user hunting for a kimi-CLI
193
+ // PATH issue when the actual missing binary is opencode.
194
+ cli: 'opencode',
195
+ timeoutMs: opts.timeoutMs,
196
+ abortSignal: opts.abortSignal,
197
+ heartbeat: true,
198
+ });
199
+ return run.events;
200
+ },
201
+ estimateCostUsd() {
202
+ // Kimi CLI uses Moonshot subscription on the user's plan, not metered API.
203
+ return 0;
204
+ },
205
+ };
206
+ //# sourceMappingURL=kimi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kimi.js","sourceRoot":"","sources":["../../../src/daemon/agents/kimi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ /**
3
+ * OpenCode agent shim (Kimi/DeepSeek via OpenCode Go plan).
4
+ * Single-line prompts, plain text paths (see feedback_gemini_multiline_prompts.md).
5
+ * Always /clear between rounds (see feedback_opencode_clear_always.md).
6
+ * Never lead with `/` (slash-command) or `@` (file-attach popup).
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.opencodeShim = void 0;
43
+ exports.wrapWithPty = wrapWithPty;
44
+ const quote_js_1 = require("./quote.js");
45
+ const headless_js_1 = require("../headless.js");
46
+ const index_js_1 = require("./parsers/index.js");
47
+ const sandbox_guard_js_1 = require("./sandbox-guard.js");
48
+ const fs = __importStar(require("fs"));
49
+ const path = __importStar(require("path"));
50
+ const os = __importStar(require("os"));
51
+ /**
52
+ * Wrap a command in a PTY using `script` so the child sees stdout as a TTY.
53
+ *
54
+ * Why opencode needs this: opencode 1.14.x's `run --format json` calls
55
+ * isatty(stdout) before emitting any output. When stdout is a pipe (which
56
+ * is always true under our spawnHeadless path), it produces zero bytes —
57
+ * the model still runs to completion (visible in opencode's debug log)
58
+ * but nothing reaches our parser. PTY wrapping is the only known fix
59
+ * short of upstream patching opencode.
60
+ *
61
+ * Cross-platform notes:
62
+ * - Linux (util-linux script ≥2.39): `script -qfec "<quoted>" /dev/null`
63
+ * -q suppresses header/footer, -f flushes after every write (no JSON
64
+ * buffering), -e forwards the child's exit code so cli_failed
65
+ * detection still works, -c runs a single command instead of a shell.
66
+ * - macOS (BSD script): `script -q /dev/null <cmd> <args...>` — the
67
+ * command is positional, no -c, no -f (BSD script always flushes).
68
+ * - Anywhere else (Windows, missing `script`): pass through unwrapped.
69
+ * The reviewer runner's "no events at all" safety net (added in the
70
+ * same fix) will surface a `## REVIEWER FAILED · no_output` instead
71
+ * of a silent 0-byte answer.
72
+ */
73
+ function wrapWithPty(cmd, args) {
74
+ const platform = os.platform();
75
+ if (platform === 'linux') {
76
+ // Shell-quote each arg; util-linux script -c parses the string with shell rules.
77
+ const quoted = [cmd, ...args]
78
+ .map((a) => `'${a.replace(/'/g, `'\\''`)}'`)
79
+ .join(' ');
80
+ return { command: 'script', args: ['-qfec', quoted, '/dev/null'] };
81
+ }
82
+ if (platform === 'darwin') {
83
+ return { command: 'script', args: ['-q', '/dev/null', cmd, ...args] };
84
+ }
85
+ return { command: cmd, args: [...args] };
86
+ }
87
+ exports.opencodeShim = {
88
+ lineage: 'opencode',
89
+ name: 'opencode-cli',
90
+ // clearKeys are sent by the runner via mgr.sendKeys() before nudging.
91
+ // Pattern: Escape twice to dismiss overlays, then /clear + Enter.
92
+ clearKeys: ['Escape', 'Escape', '/clear', 'Enter'],
93
+ // Auto-recovery for OpenCode's permission dialog (bash command, file read,
94
+ // subagent spawn — same dialog shape, different triggers).
95
+ //
96
+ // OpenCode 1.14.x shows a TWO-STEP dialog when the user picks "Allow always":
97
+ // 1. First dialog (3 buttons, default = leftmost "Allow once"):
98
+ // Allow once Allow always Reject
99
+ // → `Right` moves the highlight from "Allow once" to "Allow always".
100
+ // → `Enter` confirms and pops the second dialog.
101
+ // 2. Nested confirm (2 buttons, default = leftmost "Confirm"):
102
+ // △ Always allow
103
+ // This will allow the following patterns until OpenCode is restarted:
104
+ // - cat *
105
+ // Confirm Cancel
106
+ // → `Enter` confirms (default selection is "Confirm"). Dialog dismisses.
107
+ //
108
+ // Earlier `[Right, Enter]` only cleared step 1; step 2 sat there forever, the
109
+ // detector's dedup suppressed re-emission of `permission_prompt` (same kind),
110
+ // and the reviewer phase eventually timed out with no answer. Worse: if the
111
+ // dedup ever cleared (e.g. pane redraw scrolled "Always allow" off-screen)
112
+ // and a fresh recovery fired on dialog 2, `Right` would move "Confirm" →
113
+ // "Cancel" and `Enter` would REJECT the command. This sequence sends all
114
+ // three keys atomically via a single `tmux send-keys` call — bubbletea
115
+ // queues them and processes one at a time, so even if dialog 2 hasn't
116
+ // rendered yet when the third Enter arrives, it's queued and consumed when
117
+ // the input loop next polls.
118
+ //
119
+ // Same dialog shape covers every recoverable opencode prompt we've seen
120
+ // (git diff, Read on external path, Task subagent spawn). If a future
121
+ // opencode reorders buttons or adds a step 3, this sequence may fail
122
+ // safely (extra Enters land as harmless newlines in chat input) — phase
123
+ // timeout will catch it. See error-detector.ts for the matching narrowed
124
+ // regex that prevents false-positives on the nested step-2 heading.
125
+ recoverKeys: {
126
+ permission_prompt: ['Right', 'Enter', 'Enter'],
127
+ },
128
+ buildLaunchCommand(opts) {
129
+ (0, quote_js_1.validateValue)('model', opts.model);
130
+ // Fail-closed when the user requested strict sandbox: the opencode
131
+ // CLI doesn't expose a read-only flag we can map to. Pre-fix we
132
+ // silently spawned anyway and the "Strict" label became decorative
133
+ // for any opencode-routed reviewer (Audit D1 BLOCKER). Throwing
134
+ // here surfaces in the runner as a `cli_error` with an actionable
135
+ // message; the user can switch to a lineage that supports strict
136
+ // (claude / codex / gemini) or fall back to workspace.
137
+ (0, sandbox_guard_js_1.assertSandboxSupported)(opts.sandbox, 'opencode');
138
+ const cwd = (0, quote_js_1.quotePath)(opts.cwd);
139
+ let cmd = `cd ${cwd} && opencode`;
140
+ if (opts.model) {
141
+ cmd += ` --model ${opts.model}`;
142
+ }
143
+ return cmd;
144
+ },
145
+ formatPrompt(opts) {
146
+ // CRITICAL: Single-line only. Never lead with `/` or `@`.
147
+ // Plain text path reference: "at /abs/path" form.
148
+ const sentinel = opts.expectDoneSentinel ? ' End with ## DONE.' : '';
149
+ return (`Open the file at this absolute path using your read tool: ${opts.promptFile} ` +
150
+ `— follow the <ask> block, write your full answer to ${opts.answerFile}.${sentinel}`);
151
+ },
152
+ /**
153
+ * Headless mode (`opencode run --format json "<tiny argv> @prompt.md"`).
154
+ *
155
+ * OpenCode `run` is one-shot — emits a single JSON blob at the end with
156
+ * the final message. parseOpencode returns [] on every line; the on-exit
157
+ * handler parses the full blob into a message_done event. Heartbeat is on
158
+ * so the UI shows the agent is alive during the silent run.
159
+ *
160
+ * Argv-overflow guard: opencode's `run` only accepts the prompt as a
161
+ * positional argv (no stdin support — verified 2026-05-02 with `opencode
162
+ * run --help`). For chorus self-reviews on real PR diffs the prompt
163
+ * crosses 100KB and shell-quoting / ARG_MAX bites. Workaround mirrors
164
+ * the tmux path: write the prompt to `<cwd>/prompt.md` and pass a tiny
165
+ * directive on argv telling opencode to read that file using its read
166
+ * tool. The chat dir is always the cwd, so the relative path resolves
167
+ * inside opencode's allowed workspace.
168
+ */
169
+ runHeadless(opts) {
170
+ // Same fail-closed gate as the tmux path. See buildLaunchCommand
171
+ // above for rationale. Returns a single-shot async iterable that
172
+ // yields one error event so the runner records cli_error and the
173
+ // cockpit shows the user a clear "switch lineage" message instead
174
+ // of pretending the run completed normally.
175
+ const sandboxError = (0, sandbox_guard_js_1.sandboxFailClosed)(opts.sandbox, 'opencode');
176
+ if (sandboxError)
177
+ return sandboxError;
178
+ // Sidestep both ARG_MAX and shell-escape pitfalls by stashing the prompt
179
+ // on disk. The chat dir already exists (the runner creates it before
180
+ // spawning), so this never fails on first call.
181
+ const promptPath = path.join(opts.cwd, 'prompt.md');
182
+ fs.writeFileSync(promptPath, opts.promptText, 'utf-8');
183
+ // CRITICAL: Single-line message. Never lead with `/` or `@`.
184
+ // Plain text path reference matches the tmux formatPrompt pattern.
185
+ // Don't tell opencode to write answer.md — the runner captures stdout
186
+ // JSON via parseOpencodeExit and writes the file itself; a tool-side
187
+ // write would race with the runner's clobber on message_done.
188
+ const directive = `Open the file at this absolute path using your read tool: ${promptPath} ` +
189
+ `— follow the instructions inside exactly and respond with your full answer in this conversation, ending with ## DONE.`;
190
+ const opencodeArgs = ['run', '--format', 'json'];
191
+ if (opts.model)
192
+ opencodeArgs.push('--model', opts.model);
193
+ opencodeArgs.push(directive);
194
+ // PTY wrapping is non-optional: opencode 1.14.x's `run --format json`
195
+ // checks isatty(stdout) and refuses to emit JSON when stdout is a pipe.
196
+ // The headless path here always pipes stdout (spawn child_process), so
197
+ // without a PTY the child runs the model to completion (visible in the
198
+ // opencode log under `service=bus type=message.part.delta publishing`)
199
+ // but never writes a single byte to our pipe. The watcher then sees an
200
+ // empty stream, no message_done, no error — answer.md ends up 0 bytes
201
+ // and the reviewer card renders "errored — didn't produce any output".
202
+ //
203
+ // util-linux `script -qfec "<cmd>" /dev/null` allocates a PTY on stdout
204
+ // for the wrapped command; -q suppresses script's header/footer; -f
205
+ // flushes after every write so JSON-Lines arrive in real time; -e
206
+ // forwards the child exit code so cli_failed detection still works.
207
+ // Header/footer are absent under -q, so parseOpencode (which already
208
+ // tryJson's every line and discards non-JSON) needs no change.
209
+ const { command, args } = wrapWithPty('opencode', opencodeArgs);
210
+ const run = (0, headless_js_1.spawnHeadless)({
211
+ command,
212
+ args,
213
+ cwd: opts.cwd,
214
+ parseLine: index_js_1.parseOpencode,
215
+ onExit: (fullStdout) => (0, index_js_1.parseOpencodeExit)(fullStdout),
216
+ cli: 'opencode',
217
+ timeoutMs: opts.timeoutMs,
218
+ abortSignal: opts.abortSignal,
219
+ heartbeat: true, // one-shot — heartbeat keeps UI alive
220
+ });
221
+ return run.events;
222
+ },
223
+ estimateCostUsd() {
224
+ // OpenCode Go subscription plan (Kimi/DeepSeek), not per-call API
225
+ return 0;
226
+ },
227
+ };
228
+ //# sourceMappingURL=opencode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/daemon/agents/opencode.ts"],"names":[],"mappings":"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"}