chorus-codes 0.7.0 → 0.7.1

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 (291) 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/fallback-build-manifest.json +3 -3
  6. package/.next/prerender-manifest.json +3 -3
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found.html +1 -1
  15. package/.next/server/app/_not-found.rsc +1 -1
  16. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  22. package/.next/server/app/new.html +1 -1
  23. package/.next/server/app/new.rsc +1 -1
  24. package/.next/server/app/new.segments/_full.segment.rsc +1 -1
  25. package/.next/server/app/new.segments/_head.segment.rsc +1 -1
  26. package/.next/server/app/new.segments/_index.segment.rsc +1 -1
  27. package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
  28. package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +1 -1
  29. package/.next/server/app/new.segments/new.segment.rsc +1 -1
  30. package/.next/server/app/onboarding.html +1 -1
  31. package/.next/server/app/onboarding.rsc +1 -1
  32. package/.next/server/app/onboarding.segments/_full.segment.rsc +1 -1
  33. package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
  34. package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
  35. package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
  36. package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
  37. package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
  38. package/.next/server/app/personas.html +1 -1
  39. package/.next/server/app/personas.rsc +1 -1
  40. package/.next/server/app/personas.segments/_full.segment.rsc +1 -1
  41. package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
  42. package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
  43. package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
  44. package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +1 -1
  45. package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
  46. package/.next/server/app/settings.html +1 -1
  47. package/.next/server/app/settings.rsc +1 -1
  48. package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
  49. package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
  50. package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
  51. package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
  52. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
  53. package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
  54. package/.next/server/app/templates.html +1 -1
  55. package/.next/server/app/templates.rsc +1 -1
  56. package/.next/server/app/templates.segments/_full.segment.rsc +1 -1
  57. package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
  58. package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
  59. package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
  60. package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +1 -1
  61. package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
  62. package/.next/server/middleware-build-manifest.js +3 -3
  63. package/.next/server/pages/404.html +1 -1
  64. package/.next/server/pages/500.html +1 -1
  65. package/.next/server/server-reference-manifest.js +1 -1
  66. package/.next/server/server-reference-manifest.json +1 -1
  67. package/.next/trace +1 -1
  68. package/.next/trace-build +1 -1
  69. package/dist/cli/commands/doctor.js +116 -0
  70. package/dist/cli/commands/doctor.js.map +1 -0
  71. package/dist/cli/commands/init.js +211 -0
  72. package/dist/cli/commands/init.js.map +1 -0
  73. package/dist/cli/commands/start.js +240 -0
  74. package/dist/cli/commands/start.js.map +1 -0
  75. package/dist/cli/commands/status.js +54 -0
  76. package/dist/cli/commands/status.js.map +1 -0
  77. package/dist/cli/commands/stop.js +97 -0
  78. package/dist/cli/commands/stop.js.map +1 -0
  79. package/dist/cli/connect.js +108 -0
  80. package/dist/cli/connect.js.map +1 -0
  81. package/dist/cli/index.js +99 -0
  82. package/dist/cli/index.js.map +1 -0
  83. package/dist/cli/port-utils.js +260 -0
  84. package/dist/cli/port-utils.js.map +1 -0
  85. package/dist/cli/runtime-env.js +60 -0
  86. package/dist/cli/runtime-env.js.map +1 -0
  87. package/dist/cli/shared.js +54 -0
  88. package/dist/cli/shared.js.map +1 -0
  89. package/dist/cli/ui.js +60 -0
  90. package/dist/cli/ui.js.map +1 -0
  91. package/dist/daemon/agents/claude.js +98 -0
  92. package/dist/daemon/agents/claude.js.map +1 -0
  93. package/dist/daemon/agents/codex.js +160 -0
  94. package/dist/daemon/agents/codex.js.map +1 -0
  95. package/dist/daemon/agents/gemini.js +111 -0
  96. package/dist/daemon/agents/gemini.js.map +1 -0
  97. package/dist/daemon/agents/index.js +59 -0
  98. package/dist/daemon/agents/index.js.map +1 -0
  99. package/dist/daemon/agents/kimi.js +206 -0
  100. package/dist/daemon/agents/kimi.js.map +1 -0
  101. package/dist/daemon/agents/opencode.js +228 -0
  102. package/dist/daemon/agents/opencode.js.map +1 -0
  103. package/dist/daemon/agents/openrouter.js +274 -0
  104. package/dist/daemon/agents/openrouter.js.map +1 -0
  105. package/dist/daemon/agents/parsers/claude.js +63 -0
  106. package/dist/daemon/agents/parsers/claude.js.map +1 -0
  107. package/dist/daemon/agents/parsers/codex.js +51 -0
  108. package/dist/daemon/agents/parsers/codex.js.map +1 -0
  109. package/dist/daemon/agents/parsers/gemini.js +144 -0
  110. package/dist/daemon/agents/parsers/gemini.js.map +1 -0
  111. package/dist/daemon/agents/parsers/index.js +31 -0
  112. package/dist/daemon/agents/parsers/index.js.map +1 -0
  113. package/dist/daemon/agents/parsers/kimi.js +8 -0
  114. package/dist/daemon/agents/parsers/kimi.js.map +1 -0
  115. package/dist/daemon/agents/parsers/opencode.js +105 -0
  116. package/dist/daemon/agents/parsers/opencode.js.map +1 -0
  117. package/dist/daemon/agents/parsers/openrouter.js +69 -0
  118. package/dist/daemon/agents/parsers/openrouter.js.map +1 -0
  119. package/dist/daemon/agents/parsers/shared.js +17 -0
  120. package/dist/daemon/agents/parsers/shared.js.map +1 -0
  121. package/dist/daemon/agents/preflight.js +83 -0
  122. package/dist/daemon/agents/preflight.js.map +1 -0
  123. package/dist/daemon/agents/quote.js +45 -0
  124. package/dist/daemon/agents/quote.js.map +1 -0
  125. package/dist/daemon/agents/sandbox-guard.js +69 -0
  126. package/dist/daemon/agents/sandbox-guard.js.map +1 -0
  127. package/dist/daemon/agents/types.js +6 -0
  128. package/dist/daemon/agents/types.js.map +1 -0
  129. package/dist/daemon/api-response.js +65 -0
  130. package/dist/daemon/api-response.js.map +1 -0
  131. package/dist/daemon/error-detector.js +329 -0
  132. package/dist/daemon/error-detector.js.map +1 -0
  133. package/dist/daemon/headless.js +533 -0
  134. package/dist/daemon/headless.js.map +1 -0
  135. package/dist/daemon/index.js +333 -0
  136. package/dist/daemon/index.js.map +1 -0
  137. package/dist/daemon/openrouter.js +192 -0
  138. package/dist/daemon/openrouter.js.map +1 -0
  139. package/dist/daemon/orchestrators/claude.js +163 -0
  140. package/dist/daemon/orchestrators/claude.js.map +1 -0
  141. package/dist/daemon/orchestrators/codex.js +101 -0
  142. package/dist/daemon/orchestrators/codex.js.map +1 -0
  143. package/dist/daemon/orchestrators/cursor-windsurf.js +118 -0
  144. package/dist/daemon/orchestrators/cursor-windsurf.js.map +1 -0
  145. package/dist/daemon/orchestrators/gemini.js +108 -0
  146. package/dist/daemon/orchestrators/gemini.js.map +1 -0
  147. package/dist/daemon/orchestrators/index.js +90 -0
  148. package/dist/daemon/orchestrators/index.js.map +1 -0
  149. package/dist/daemon/orchestrators/kimi.js +108 -0
  150. package/dist/daemon/orchestrators/kimi.js.map +1 -0
  151. package/dist/daemon/orchestrators/opencode.js +152 -0
  152. package/dist/daemon/orchestrators/opencode.js.map +1 -0
  153. package/dist/daemon/orchestrators/shared.js +60 -0
  154. package/dist/daemon/orchestrators/shared.js.map +1 -0
  155. package/dist/daemon/output-watcher.js +131 -0
  156. package/dist/daemon/output-watcher.js.map +1 -0
  157. package/dist/daemon/participant-aborts.js +123 -0
  158. package/dist/daemon/participant-aborts.js.map +1 -0
  159. package/dist/daemon/reaper.js +46 -0
  160. package/dist/daemon/reaper.js.map +1 -0
  161. package/dist/daemon/routes/chats-events.js +62 -0
  162. package/dist/daemon/routes/chats-events.js.map +1 -0
  163. package/dist/daemon/routes/chats-stream.js +241 -0
  164. package/dist/daemon/routes/chats-stream.js.map +1 -0
  165. package/dist/daemon/routes/chats-validation.js +13 -0
  166. package/dist/daemon/routes/chats-validation.js.map +1 -0
  167. package/dist/daemon/routes/chats.js +545 -0
  168. package/dist/daemon/routes/chats.js.map +1 -0
  169. package/dist/daemon/routes/openrouter.js +103 -0
  170. package/dist/daemon/routes/openrouter.js.map +1 -0
  171. package/dist/daemon/routes/settings.js +199 -0
  172. package/dist/daemon/routes/settings.js.map +1 -0
  173. package/dist/daemon/routes/stats.js +155 -0
  174. package/dist/daemon/routes/stats.js.map +1 -0
  175. package/dist/daemon/routes/system.js +208 -0
  176. package/dist/daemon/routes/system.js.map +1 -0
  177. package/dist/daemon/routes/templates-personas.js +254 -0
  178. package/dist/daemon/routes/templates-personas.js.map +1 -0
  179. package/dist/daemon/routes/voices.js +139 -0
  180. package/dist/daemon/routes/voices.js.map +1 -0
  181. package/dist/daemon/runner/doer-driver.js +346 -0
  182. package/dist/daemon/runner/doer-driver.js.map +1 -0
  183. package/dist/daemon/runner/doer.js +336 -0
  184. package/dist/daemon/runner/doer.js.map +1 -0
  185. package/dist/daemon/runner/prior-round.js +140 -0
  186. package/dist/daemon/runner/prior-round.js.map +1 -0
  187. package/dist/daemon/runner/prompt-builder.js +292 -0
  188. package/dist/daemon/runner/prompt-builder.js.map +1 -0
  189. package/dist/daemon/runner/review-only-phase.js +103 -0
  190. package/dist/daemon/runner/review-only-phase.js.map +1 -0
  191. package/dist/daemon/runner/reviewer-driver.js +410 -0
  192. package/dist/daemon/runner/reviewer-driver.js.map +1 -0
  193. package/dist/daemon/runner/reviewer.js +384 -0
  194. package/dist/daemon/runner/reviewer.js.map +1 -0
  195. package/dist/daemon/runner/run-with-fallback.js +56 -0
  196. package/dist/daemon/runner/run-with-fallback.js.map +1 -0
  197. package/dist/daemon/runner/sanitize-name.js +8 -0
  198. package/dist/daemon/runner/sanitize-name.js.map +1 -0
  199. package/dist/daemon/runner/stream-file-writer.js +116 -0
  200. package/dist/daemon/runner/stream-file-writer.js.map +1 -0
  201. package/dist/daemon/runner/swap-sidecar.js +102 -0
  202. package/dist/daemon/runner/swap-sidecar.js.map +1 -0
  203. package/dist/daemon/runner/template-fallback.js +119 -0
  204. package/dist/daemon/runner/template-fallback.js.map +1 -0
  205. package/dist/daemon/runner/types.js +3 -0
  206. package/dist/daemon/runner/types.js.map +1 -0
  207. package/dist/daemon/runner/verdict.js +51 -0
  208. package/dist/daemon/runner/verdict.js.map +1 -0
  209. package/dist/daemon/runner-multiplex.js +364 -0
  210. package/dist/daemon/runner-multiplex.js.map +1 -0
  211. package/dist/daemon/runner.js +427 -0
  212. package/dist/daemon/runner.js.map +1 -0
  213. package/dist/daemon/ship.js +340 -0
  214. package/dist/daemon/ship.js.map +1 -0
  215. package/dist/daemon/template-cache.js +37 -0
  216. package/dist/daemon/template-cache.js.map +1 -0
  217. package/dist/daemon/tmux-types.js +9 -0
  218. package/dist/daemon/tmux-types.js.map +1 -0
  219. package/dist/daemon/tmux.js +341 -0
  220. package/dist/daemon/tmux.js.map +1 -0
  221. package/dist/lib/atomic-write.js +55 -0
  222. package/dist/lib/atomic-write.js.map +1 -0
  223. package/dist/lib/chat-events-bus.js +27 -0
  224. package/dist/lib/chat-events-bus.js.map +1 -0
  225. package/dist/lib/chat-slug.js +105 -0
  226. package/dist/lib/chat-slug.js.map +1 -0
  227. package/dist/lib/cli-detect.js +388 -0
  228. package/dist/lib/cli-detect.js.map +1 -0
  229. package/dist/lib/cli-health.js +156 -0
  230. package/dist/lib/cli-health.js.map +1 -0
  231. package/dist/lib/cli-paths.js +113 -0
  232. package/dist/lib/cli-paths.js.map +1 -0
  233. package/dist/lib/cli-precheck.js +141 -0
  234. package/dist/lib/cli-precheck.js.map +1 -0
  235. package/dist/lib/db/chats.js +244 -0
  236. package/dist/lib/db/chats.js.map +1 -0
  237. package/dist/lib/db/connection.js +254 -0
  238. package/dist/lib/db/connection.js.map +1 -0
  239. package/dist/lib/db/index.js +34 -0
  240. package/dist/lib/db/index.js.map +1 -0
  241. package/dist/lib/db/personas.js +65 -0
  242. package/dist/lib/db/personas.js.map +1 -0
  243. package/dist/lib/db/phase-events.js +172 -0
  244. package/dist/lib/db/phase-events.js.map +1 -0
  245. package/dist/lib/db/secrets.js +53 -0
  246. package/dist/lib/db/secrets.js.map +1 -0
  247. package/dist/lib/db/settings.js +47 -0
  248. package/dist/lib/db/settings.js.map +1 -0
  249. package/dist/lib/db/templates.js +75 -0
  250. package/dist/lib/db/templates.js.map +1 -0
  251. package/dist/lib/db/voices.js +184 -0
  252. package/dist/lib/db/voices.js.map +1 -0
  253. package/dist/lib/lineage-maps.js +200 -0
  254. package/dist/lib/lineage-maps.js.map +1 -0
  255. package/dist/lib/logger.js +186 -0
  256. package/dist/lib/logger.js.map +1 -0
  257. package/dist/lib/personas.js +117 -0
  258. package/dist/lib/personas.js.map +1 -0
  259. package/dist/lib/runtime-path.js +222 -0
  260. package/dist/lib/runtime-path.js.map +1 -0
  261. package/dist/lib/settings/billing.js +58 -0
  262. package/dist/lib/settings/billing.js.map +1 -0
  263. package/dist/lib/settings/permissions.js +81 -0
  264. package/dist/lib/settings/permissions.js.map +1 -0
  265. package/dist/lib/settings/transport.js +113 -0
  266. package/dist/lib/settings/transport.js.map +1 -0
  267. package/dist/lib/telemetry.js +290 -0
  268. package/dist/lib/telemetry.js.map +1 -0
  269. package/dist/lib/template-schema.js +319 -0
  270. package/dist/lib/template-schema.js.map +1 -0
  271. package/dist/lib/template-validation.js +82 -0
  272. package/dist/lib/template-validation.js.map +1 -0
  273. package/dist/lib/voices.js +533 -0
  274. package/dist/lib/voices.js.map +1 -0
  275. package/dist/mcp/client.js +138 -0
  276. package/dist/mcp/client.js.map +1 -0
  277. package/dist/mcp/index.js +178 -0
  278. package/dist/mcp/index.js.map +1 -0
  279. package/dist/mcp/tools.js +355 -0
  280. package/dist/mcp/tools.js.map +1 -0
  281. package/package.json +2 -1
  282. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js +0 -6077
  283. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js.map +0 -69
  284. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js +0 -6318
  285. package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js.map +0 -71
  286. package/.next/dev/types/cache-life.d.ts +0 -145
  287. package/.next/dev/types/routes.d.ts +0 -84
  288. package/.next/dev/types/validator.ts +0 -178
  289. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_buildManifest.js +0 -0
  290. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_clientMiddlewareManifest.js +0 -0
  291. /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_ssgManifest.js +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/lib/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ /**
3
+ * Persona file loader + DB seed.
4
+ *
5
+ * Built-in personas live as Markdown files with YAML frontmatter under
6
+ * `prompts/personas/<id>.md`. The daemon reads them on startup and upserts
7
+ * each into the `personas` table with `builtin = true`.
8
+ *
9
+ * Users can clone a built-in (creates a row with `builtin = false` and
10
+ * `forked_from = <original-id>`), edit, and save. Re-seeding never overwrites
11
+ * user rows — only built-in rows track the file.
12
+ */
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.seedBuiltinPersonas = seedBuiltinPersonas;
18
+ exports.listPersonas = listPersonas;
19
+ exports.getPersona = getPersona;
20
+ const fs_1 = require("fs");
21
+ const path_1 = __importDefault(require("path"));
22
+ const yaml_1 = __importDefault(require("yaml"));
23
+ const index_js_1 = require("./db/index.js");
24
+ /**
25
+ * Resolve the prompts/personas directory across dev (tsx, repo-relative)
26
+ * and published (dist, package-relative) layouts.
27
+ *
28
+ * Dev: __dirname = <repo>/src/lib → prompts dir = <repo>/prompts/personas
29
+ * Built: __dirname = <repo>/dist/lib → prompts dir = <repo>/prompts/personas (still in repo)
30
+ * Installed: __dirname = <pkg>/dist/lib → prompts dir = <pkg>/prompts/personas (shipped via "files")
31
+ */
32
+ function resolvePromptsDir() {
33
+ const candidates = [
34
+ path_1.default.resolve(__dirname, '..', '..', 'prompts', 'personas'),
35
+ path_1.default.resolve(__dirname, '..', 'prompts', 'personas'),
36
+ ];
37
+ for (const candidate of candidates) {
38
+ if ((0, fs_1.existsSync)(candidate))
39
+ return candidate;
40
+ }
41
+ throw new Error(`prompts/personas not found. Looked in:\n ${candidates.join('\n ')}`);
42
+ }
43
+ /**
44
+ * Parse a single persona .md file with YAML frontmatter.
45
+ * Frontmatter is delimited by `---` lines at the top of the file.
46
+ */
47
+ function parsePersonaFile(filePath) {
48
+ const raw = (0, fs_1.readFileSync)(filePath, 'utf-8');
49
+ if (!raw.startsWith('---\n')) {
50
+ throw new Error(`${filePath}: missing YAML frontmatter (must start with "---")`);
51
+ }
52
+ const fmEnd = raw.indexOf('\n---\n', 4);
53
+ if (fmEnd === -1) {
54
+ throw new Error(`${filePath}: unclosed YAML frontmatter (missing closing "---")`);
55
+ }
56
+ const fmText = raw.slice(4, fmEnd);
57
+ const body = raw.slice(fmEnd + 5).trim();
58
+ const fm = yaml_1.default.parse(fmText);
59
+ if (!fm?.id)
60
+ throw new Error(`${filePath}: frontmatter missing required "id"`);
61
+ if (!fm.label)
62
+ throw new Error(`${filePath}: frontmatter missing required "label"`);
63
+ if (!fm.one_liner)
64
+ throw new Error(`${filePath}: frontmatter missing required "one_liner"`);
65
+ if (!body)
66
+ throw new Error(`${filePath}: empty body (the system prompt)`);
67
+ return { frontmatter: fm, body, source_path: filePath };
68
+ }
69
+ /**
70
+ * Read every *.md file under prompts/personas and return parsed entries.
71
+ */
72
+ function loadPersonaFiles() {
73
+ const dir = resolvePromptsDir();
74
+ const files = (0, fs_1.readdirSync)(dir).filter((f) => f.endsWith('.md'));
75
+ return files.map((f) => parsePersonaFile(path_1.default.join(dir, f)));
76
+ }
77
+ /**
78
+ * Seed/refresh built-in personas in the DB from the prompt files.
79
+ * - Built-in rows are upserted on every call (file = source of truth).
80
+ * - User rows (builtin=0) are never touched.
81
+ *
82
+ * Returns the count of rows upserted.
83
+ */
84
+ async function seedBuiltinPersonas() {
85
+ const parsed = loadPersonaFiles();
86
+ let count = 0;
87
+ for (const { frontmatter, body } of parsed) {
88
+ // Skip rows the user has edited via POST /personas (which sets
89
+ // builtin=false). Without this guard, INSERT OR REPLACE in upsert()
90
+ // would clobber the user's edits on every daemon boot. Same tradeoff
91
+ // as templates: edited rows no longer auto-receive upstream changes.
92
+ const existing = await index_js_1.personas.getById(frontmatter.id);
93
+ if (existing && !existing.builtin)
94
+ continue;
95
+ await index_js_1.personas.upsert({
96
+ id: frontmatter.id,
97
+ label: frontmatter.label,
98
+ one_liner: frontmatter.one_liner,
99
+ system_prompt: body,
100
+ recommended_lineage: frontmatter.recommended_lineage ?? null,
101
+ builtin: true,
102
+ forked_from: null,
103
+ });
104
+ count++;
105
+ }
106
+ return count;
107
+ }
108
+ /**
109
+ * Public read API used by HTTP / MCP layers.
110
+ */
111
+ async function listPersonas() {
112
+ return index_js_1.personas.list();
113
+ }
114
+ async function getPersona(id) {
115
+ return index_js_1.personas.getById(id);
116
+ }
117
+ //# sourceMappingURL=personas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"personas.js","sourceRoot":"","sources":["../../src/lib/personas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,222 @@
1
+ "use strict";
2
+ /**
3
+ * Runtime PATH resolution for headless CLI subprocess spawns.
4
+ *
5
+ * Why this module exists
6
+ * ----------------------
7
+ * The chorus daemon spawns reviewer CLIs (claude, codex, gemini, opencode,
8
+ * kimi) as headless subprocesses. Those subprocesses inherit the daemon's
9
+ * PATH — which is whatever PATH was set for the process that launched the
10
+ * daemon.
11
+ *
12
+ * That PATH is frequently INSUFFICIENT for finding the CLIs:
13
+ *
14
+ * - Linux opencode installs to `~/.opencode/bin/`, exported via .bashrc.
15
+ * The daemon usually starts from a non-interactive shell that skips
16
+ * .bashrc (early-return on `[ -z "$PS1" ]`), so opencode is missing.
17
+ * - macOS Homebrew installs to /opt/homebrew/bin (Apple Silicon) or
18
+ * /usr/local/bin (Intel). LaunchAgent / tray-app starts inherit a
19
+ * minimal PATH that may exclude either.
20
+ * - asdf / volta / pnpm shim dirs live under $HOME/.tool-versions/...
21
+ * and only land on PATH via shellenv hooks.
22
+ *
23
+ * The fix has three layers, all stacked here:
24
+ *
25
+ * 1. **Captured interactive PATH** — `chorus init` and `chorus start`
26
+ * run `$SHELL -lic 'echo $PATH'` once and stash the result in the
27
+ * `runtime.captured_path` setting. Subsequent daemon spawns merge
28
+ * it in, so if the user can run `opencode` from their terminal, the
29
+ * daemon can run it too.
30
+ * 2. **Known-install dirs** — common per-tool install locations
31
+ * (`~/.opencode/bin`, `~/.codex/bin`, `/opt/homebrew/bin`, …) are
32
+ * auto-prepended when they exist on disk. Belt-and-braces for tray-
33
+ * app launches that have no terminal to capture from.
34
+ * 3. **Manual paths** — when the user pastes a custom path in the
35
+ * onboarding "I know where it is" affordance, the dirname of that
36
+ * path is added too. Ensures bare-binary spawns still work even when
37
+ * the binary lives in a fully custom location.
38
+ *
39
+ * This module is import-time stateful but reads `settings` lazily, so
40
+ * tests can swap CHORUS_DB_PATH without restarting the process.
41
+ */
42
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
43
+ if (k2 === undefined) k2 = k;
44
+ var desc = Object.getOwnPropertyDescriptor(m, k);
45
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
46
+ desc = { enumerable: true, get: function() { return m[k]; } };
47
+ }
48
+ Object.defineProperty(o, k2, desc);
49
+ }) : (function(o, m, k, k2) {
50
+ if (k2 === undefined) k2 = k;
51
+ o[k2] = m[k];
52
+ }));
53
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
54
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
55
+ }) : function(o, v) {
56
+ o["default"] = v;
57
+ });
58
+ var __importStar = (this && this.__importStar) || (function () {
59
+ var ownKeys = function(o) {
60
+ ownKeys = Object.getOwnPropertyNames || function (o) {
61
+ var ar = [];
62
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
63
+ return ar;
64
+ };
65
+ return ownKeys(o);
66
+ };
67
+ return function (mod) {
68
+ if (mod && mod.__esModule) return mod;
69
+ var result = {};
70
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
71
+ __setModuleDefault(result, mod);
72
+ return result;
73
+ };
74
+ })();
75
+ Object.defineProperty(exports, "__esModule", { value: true });
76
+ exports.captureInteractivePath = captureInteractivePath;
77
+ exports.persistCapturedPath = persistCapturedPath;
78
+ exports.loadCapturedPath = loadCapturedPath;
79
+ exports.buildRuntimePath = buildRuntimePath;
80
+ exports.buildRuntimeEnv = buildRuntimeEnv;
81
+ const node_child_process_1 = require("node:child_process");
82
+ const fs = __importStar(require("node:fs"));
83
+ const os = __importStar(require("node:os"));
84
+ const path = __importStar(require("node:path"));
85
+ const settings_js_1 = require("./db/settings.js");
86
+ const SETTINGS_KEY_CAPTURED_PATH = 'runtime.captured_path';
87
+ /**
88
+ * Per-tool install locations that live OUTSIDE the typical /usr/local/bin
89
+ * default PATH. Order matters only when two contain the same binary; we
90
+ * dedupe on output. macOS-only paths are kept on Linux too — fs.existsSync
91
+ * filters them out so there's no harm in leaving them in the list.
92
+ */
93
+ const KNOWN_INSTALL_DIRS = [
94
+ '~/.opencode/bin',
95
+ '~/.codex/bin',
96
+ '~/.gemini/bin',
97
+ '~/.kimi/bin',
98
+ '~/.claude/local',
99
+ '~/.bun/bin',
100
+ '~/.deno/bin',
101
+ '~/.cargo/bin',
102
+ '~/.local/bin',
103
+ '/opt/homebrew/bin',
104
+ '/usr/local/bin',
105
+ ];
106
+ function expandHome(p) {
107
+ if (p.startsWith('~/'))
108
+ return path.join(os.homedir(), p.slice(2));
109
+ if (p === '~')
110
+ return os.homedir();
111
+ return p;
112
+ }
113
+ /**
114
+ * Run the user's interactive login shell and ask for its PATH. Captures
115
+ * everything PATH-modifying init scripts add — .bashrc, .zshrc, asdf
116
+ * shims, fnm/nvm setup, fish abbreviations.
117
+ *
118
+ * Returns null when:
119
+ * - $SHELL is unset (e.g. some CI environments)
120
+ * - The shell exec itself fails (timeout, missing binary)
121
+ * - The shell prints something that doesn't look like a PATH
122
+ *
123
+ * Caller is expected to fall back gracefully on null — e.g. keep the
124
+ * previously-saved value or use process.env.PATH as-is.
125
+ */
126
+ function captureInteractivePath() {
127
+ const shell = process.env.SHELL;
128
+ if (!shell)
129
+ return null;
130
+ if (process.platform === 'win32')
131
+ return null; // PowerShell capture is a different code path; not implemented yet.
132
+ try {
133
+ // -l: login shell (loads .profile / .zprofile)
134
+ // -i: interactive (loads .bashrc / .zshrc — most rc files early-return
135
+ // on non-interactive, so this flag is essential)
136
+ // -c: command + exit
137
+ const out = (0, node_child_process_1.execSync)(`${shell} -lic 'echo $PATH'`, {
138
+ timeout: 5_000,
139
+ stdio: ['ignore', 'pipe', 'ignore'],
140
+ })
141
+ .toString('utf-8')
142
+ .trim();
143
+ if (!out || !out.includes('/'))
144
+ return null;
145
+ return out;
146
+ }
147
+ catch {
148
+ // Common failure modes:
149
+ // - User's rc file errors on non-tty stdout
150
+ // - 5s timeout (rc does network I/O)
151
+ // - SHELL points at a binary that doesn't exist
152
+ return null;
153
+ }
154
+ }
155
+ /**
156
+ * Persist the captured interactive PATH so the daemon can read it on
157
+ * boot. Called from `chorus init` and `chorus start`. Best-effort:
158
+ * settings write failures don't block startup — the daemon falls back
159
+ * to known-install dirs + process.env.PATH.
160
+ */
161
+ async function persistCapturedPath(value) {
162
+ await settings_js_1.settings.set(SETTINGS_KEY_CAPTURED_PATH, value);
163
+ }
164
+ async function loadCapturedPath() {
165
+ const raw = await settings_js_1.settings.get(SETTINGS_KEY_CAPTURED_PATH);
166
+ return typeof raw === 'string' && raw.length > 0 ? raw : null;
167
+ }
168
+ /**
169
+ * Build the merged PATH for a daemon-spawned subprocess. Composition,
170
+ * front-to-back (front wins on duplicate binaries):
171
+ *
172
+ * 1. Existing process.env.PATH — daemon's own runtime
173
+ * 2. Captured interactive PATH — what the user's shell sees
174
+ * 3. Known install dirs (existing) — ~/.opencode/bin, etc.
175
+ * 4. Manual-path dirs — dirnames of saved cli_paths
176
+ *
177
+ * Dedup on output. Caller is expected to pass `additionalDirs` from
178
+ * `cli-paths.ts` — keeping the dependency one-way (this module doesn't
179
+ * import from cli-paths to avoid a circular import on the settings
180
+ * helpers).
181
+ */
182
+ async function buildRuntimePath(opts) {
183
+ const parts = [];
184
+ if (process.env.PATH)
185
+ parts.push(process.env.PATH);
186
+ const captured = await loadCapturedPath();
187
+ if (captured)
188
+ parts.push(captured);
189
+ for (const dir of KNOWN_INSTALL_DIRS) {
190
+ const expanded = expandHome(dir);
191
+ if (fs.existsSync(expanded))
192
+ parts.push(expanded);
193
+ }
194
+ for (const dir of opts?.additionalDirs ?? []) {
195
+ if (dir && fs.existsSync(dir))
196
+ parts.push(dir);
197
+ }
198
+ // Dedupe while preserving first-occurrence order.
199
+ const seen = new Set();
200
+ const out = [];
201
+ for (const part of parts) {
202
+ for (const dir of part.split(path.delimiter)) {
203
+ if (!dir || seen.has(dir))
204
+ continue;
205
+ seen.add(dir);
206
+ out.push(dir);
207
+ }
208
+ }
209
+ return out.join(path.delimiter);
210
+ }
211
+ /**
212
+ * Convenience wrapper for the common spawn case — merge the runtime
213
+ * PATH into a copy of process.env. Subprocess inherits everything else
214
+ * unchanged.
215
+ */
216
+ async function buildRuntimeEnv(opts) {
217
+ return {
218
+ ...process.env,
219
+ PATH: await buildRuntimePath(opts),
220
+ };
221
+ }
222
+ //# sourceMappingURL=runtime-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-path.js","sourceRoot":"","sources":["../../src/lib/runtime-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * Billing-mode setting. Captures whether the user pays for the CLIs
4
+ * chorus drives via per-token API keys, monthly subscriptions, or a mix.
5
+ *
6
+ * Why this matters: chorus's cost estimate on the /new page used to assume
7
+ * everyone paid spot API rates (Opus ~$15/M input, GPT-5.5 ~$3/M, etc.),
8
+ * which produced fictional dollar amounts for users on Claude Pro
9
+ * ($20/mo flat) or ChatGPT Plus. Subscription users should see "Subscription
10
+ * quota" not "$0.47" — the latter implies they're charged when they aren't.
11
+ *
12
+ * v0.7 keeps this as a single global enum. v0.8 will split into per-lineage
13
+ * overrides (Claude on subscription, Gemini on API) once we have the
14
+ * onboarding UI for it.
15
+ *
16
+ * Default is 'subscription' — the path-of-least-cost-shock for new users.
17
+ * Most people land here from a Claude Pro / ChatGPT Plus / Gemini Advanced
18
+ * subscription they already pay for; showing "$0.47 estimate" on every
19
+ * /new chat would imply per-call billing they don't owe and scare them
20
+ * off. Subscription users see "Subscription quota — ~12,000 input tokens"
21
+ * instead. API-key users flip the toggle once and never look back.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.BILLING_MODE_LABELS = exports.DEFAULT_BILLING_MODE = void 0;
25
+ exports.getBillingMode = getBillingMode;
26
+ exports.setBillingMode = setBillingMode;
27
+ const db_1 = require("../db");
28
+ const BILLING_MODE_KEY = 'billing_mode';
29
+ exports.DEFAULT_BILLING_MODE = 'subscription';
30
+ exports.BILLING_MODE_LABELS = {
31
+ api: {
32
+ label: 'Pay-per-token API keys',
33
+ description: 'You bring API keys (Anthropic, OpenAI, Google) and pay per request. Cost estimates are accurate.',
34
+ },
35
+ subscription: {
36
+ label: 'CLI subscriptions',
37
+ description: 'You run Claude Code, Codex, Gemini CLI etc. through their monthly subscriptions (Claude Pro, ChatGPT Plus, Gemini Advanced). Chorus calls them through the CLI; no per-call cost. Cost shown as "Subscription quota."',
38
+ },
39
+ mixed: {
40
+ label: 'Mixed — some subscription, some API',
41
+ description: 'A subset of CLIs are on subscriptions and a subset on API keys. Estimates show worst-case API cost; real bill may be lower.',
42
+ },
43
+ };
44
+ function isBillingMode(value) {
45
+ return value === 'api' || value === 'subscription' || value === 'mixed';
46
+ }
47
+ async function getBillingMode() {
48
+ const raw = await db_1.settings.get(BILLING_MODE_KEY);
49
+ return isBillingMode(raw) ? raw : exports.DEFAULT_BILLING_MODE;
50
+ }
51
+ async function setBillingMode(value) {
52
+ if (!isBillingMode(value)) {
53
+ throw new Error(`invalid billing mode: ${value}`);
54
+ }
55
+ await db_1.settings.set(BILLING_MODE_KEY, value);
56
+ return getBillingMode();
57
+ }
58
+ //# sourceMappingURL=billing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing.js","sourceRoot":"","sources":["../../../src/lib/settings/billing.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AA+BH,wCAGC;AAED,wCAMC;AAxCD,8BAAiC;AAIjC,MAAM,gBAAgB,GAAG,cAAc,CAAC;AAC3B,QAAA,oBAAoB,GAAgB,cAAc,CAAC;AAEnD,QAAA,mBAAmB,GAAgE;IAC9F,GAAG,EAAE;QACH,KAAK,EAAE,wBAAwB;QAC/B,WAAW,EACT,kGAAkG;KACrG;IACD,YAAY,EAAE;QACZ,KAAK,EAAE,mBAAmB;QAC1B,WAAW,EACT,uNAAuN;KAC1N;IACD,KAAK,EAAE;QACL,KAAK,EAAE,qCAAqC;QAC5C,WAAW,EACT,6HAA6H;KAChI;CACF,CAAC;AAEF,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,cAAc,IAAI,KAAK,KAAK,OAAO,CAAC;AAC1E,CAAC;AAEM,KAAK,UAAU,cAAc;IAClC,MAAM,GAAG,GAAG,MAAM,aAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACjD,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,4BAAoB,CAAC;AACzD,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,KAAkB;IACrD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,aAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO,cAAc,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ /**
3
+ * Typed accessor for chorus's permission/sandbox settings.
4
+ *
5
+ * Stored in the `settings` SQLite table as JSON-encoded values keyed by:
6
+ * - sandbox_profile: 'strict' | 'workspace' | 'full'
7
+ * - auto_approve_prompts: boolean
8
+ * - network_access: boolean (overlay on top of sandbox_profile)
9
+ *
10
+ * Defaults are conservative:
11
+ * - workspace: read+write inside chat dir, no network. Reviewers can't
12
+ * escape the chat scope or call out to the public internet.
13
+ * - auto_approve_prompts: true. We pre-approve everything we can so that
14
+ * headless reviewer spawns don't hang on UI prompts. Users on a shared
15
+ * box can flip this to false.
16
+ * - network_access: false unless template/transport specifically needs it.
17
+ *
18
+ * The runner consults these before each spawn and forwards them as
19
+ * AgentSpawnOptions to the shim. Each shim translates the abstract setting
20
+ * into the appropriate CLI flag (e.g. codex `-c sandbox_mode=read-only`,
21
+ * kimi `--afk`, gemini `--approval-mode auto_edit`).
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.PROFILE_DESCRIPTIONS = exports.DEFAULT_PERMISSIONS = void 0;
25
+ exports.getPermissions = getPermissions;
26
+ exports.setPermissions = setPermissions;
27
+ const db_1 = require("../db");
28
+ const zod_1 = require("zod");
29
+ const SandboxProfileSchema = zod_1.z.enum(['strict', 'workspace', 'full']);
30
+ exports.DEFAULT_PERMISSIONS = {
31
+ sandboxProfile: 'workspace',
32
+ autoApprovePrompts: true,
33
+ networkAccess: false,
34
+ };
35
+ const SANDBOX_KEY = 'sandbox_profile';
36
+ const AUTO_APPROVE_KEY = 'auto_approve_prompts';
37
+ const NETWORK_KEY = 'network_access';
38
+ async function getPermissions() {
39
+ const [sandboxRaw, autoApproveRaw, networkRaw] = await Promise.all([
40
+ db_1.settings.get(SANDBOX_KEY),
41
+ db_1.settings.get(AUTO_APPROVE_KEY),
42
+ db_1.settings.get(NETWORK_KEY),
43
+ ]);
44
+ const sandboxProfile = SandboxProfileSchema.safeParse(sandboxRaw);
45
+ return {
46
+ sandboxProfile: sandboxProfile.success ? sandboxProfile.data : exports.DEFAULT_PERMISSIONS.sandboxProfile,
47
+ autoApprovePrompts: typeof autoApproveRaw === 'boolean' ? autoApproveRaw : exports.DEFAULT_PERMISSIONS.autoApprovePrompts,
48
+ networkAccess: typeof networkRaw === 'boolean' ? networkRaw : exports.DEFAULT_PERMISSIONS.networkAccess,
49
+ };
50
+ }
51
+ async function setPermissions(input) {
52
+ if (input.sandboxProfile !== undefined) {
53
+ SandboxProfileSchema.parse(input.sandboxProfile);
54
+ await db_1.settings.set(SANDBOX_KEY, input.sandboxProfile);
55
+ }
56
+ if (input.autoApprovePrompts !== undefined) {
57
+ await db_1.settings.set(AUTO_APPROVE_KEY, input.autoApprovePrompts);
58
+ }
59
+ if (input.networkAccess !== undefined) {
60
+ await db_1.settings.set(NETWORK_KEY, input.networkAccess);
61
+ }
62
+ return getPermissions();
63
+ }
64
+ /**
65
+ * Human-readable description of each profile, used by onboarding + /settings UI.
66
+ */
67
+ exports.PROFILE_DESCRIPTIONS = {
68
+ strict: {
69
+ label: 'Strict',
70
+ description: 'Reviewers can only read code. No file writes, no shell exec, no network. Safest, but limits what reviewers can do (e.g. can\'t run the test suite they\'re reviewing).',
71
+ },
72
+ workspace: {
73
+ label: 'Workspace (recommended)',
74
+ description: 'Reviewers can read+write inside the chat dir and run scoped shell commands. No network. Default — fits most teams.',
75
+ },
76
+ full: {
77
+ label: 'Full access',
78
+ description: 'Reviewers run with no sandbox: write anywhere, run any command, full network. Only enable on a personal machine you trust.',
79
+ },
80
+ };
81
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../../src/lib/settings/permissions.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAyBH,wCAeC;AAED,wCAYC;AApDD,8BAAiC;AACjC,6BAAwB;AAIxB,MAAM,oBAAoB,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;AAQxD,QAAA,mBAAmB,GAAuB;IACrD,cAAc,EAAE,WAAW;IAC3B,kBAAkB,EAAE,IAAI;IACxB,aAAa,EAAE,KAAK;CACrB,CAAC;AAEF,MAAM,WAAW,GAAG,iBAAiB,CAAC;AACtC,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAChD,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAE9B,KAAK,UAAU,cAAc;IAClC,MAAM,CAAC,UAAU,EAAE,cAAc,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACjE,aAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;QACzB,aAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC;QAC9B,aAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;KAC1B,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,oBAAoB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAElE,OAAO;QACL,cAAc,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,2BAAmB,CAAC,cAAc;QACjG,kBAAkB,EAChB,OAAO,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,2BAAmB,CAAC,kBAAkB;QAC/F,aAAa,EACX,OAAO,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,2BAAmB,CAAC,aAAa;KACnF,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,KAAkC;IACrE,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;QACvC,oBAAoB,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACjD,MAAM,aAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,kBAAkB,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,aAAQ,CAAC,GAAG,CAAC,gBAAgB,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,aAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,cAAc,EAAE,CAAC;AAC1B,CAAC;AAED;;GAEG;AACU,QAAA,oBAAoB,GAAmE;IAClG,MAAM,EAAE;QACN,KAAK,EAAE,QAAQ;QACf,WAAW,EACT,wKAAwK;KAC3K;IACD,SAAS,EAAE;QACT,KAAK,EAAE,yBAAyB;QAChC,WAAW,EACT,oHAAoH;KACvH;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,aAAa;QACpB,WAAW,EACT,4HAA4H;KAC/H;CACF,CAAC"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ /**
3
+ * Typed accessor for chorus's transport setting — how shims invoke the
4
+ * underlying CLI. Two modes:
5
+ *
6
+ * - 'headless' (default): spawn the CLI in `--print` / `exec` / `run` mode,
7
+ * pipe prompt to stdin or argv, parse stream-json from stdout. No tmux,
8
+ * no TUI process resident, ~80% lower RAM, no permission prompts (the
9
+ * CLIs auto-approve in headless mode).
10
+ *
11
+ * - 'tmux' (opt-in): spawn the CLI in its interactive TUI inside a tmux
12
+ * session, send the prompt via send-keys, watch answer.md for completion.
13
+ * Higher RAM, fragile pane-scraping, but humans can attach to the tmux
14
+ * session for visual debugging — useful if you want to watch the AI
15
+ * work step-by-step.
16
+ *
17
+ * Settings UI: cockpit /settings exposes this as "Show live terminal sessions"
18
+ * (off=headless, on=tmux). No deprecation timeline — both modes are first-
19
+ * class.
20
+ *
21
+ * The runner reads this once per chat (not per phase) so flipping the
22
+ * setting mid-run is intentionally inert.
23
+ */
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.TRANSPORT_DESCRIPTIONS = exports.DEFAULT_TRANSPORT = exports.TMUX_AVAILABLE = void 0;
26
+ exports.getTransport = getTransport;
27
+ exports.setTransport = setTransport;
28
+ const db_1 = require("../db");
29
+ const zod_1 = require("zod");
30
+ const os_1 = require("os");
31
+ const child_process_1 = require("child_process");
32
+ const TransportSchema = zod_1.z.enum(['headless', 'tmux']);
33
+ const TRANSPORT_KEY = 'transport';
34
+ /**
35
+ * tmux availability check.
36
+ *
37
+ * 1. Windows has no tmux equivalent — false unconditionally.
38
+ * 2. On Unix, probe `tmux -V` once at module load. If the binary isn't on
39
+ * PATH, return false so `setTransport('tmux')` can refuse with an
40
+ * actionable install hint instead of silently letting the user opt into
41
+ * a mode whose first chat hangs.
42
+ *
43
+ * Cached at module load — tmux is rarely installed/uninstalled mid-process.
44
+ * Restart the daemon after `apt install tmux` to pick up the new state.
45
+ */
46
+ function detectTmuxBinary() {
47
+ if ((0, os_1.platform)() === 'win32')
48
+ return false;
49
+ const result = (0, child_process_1.spawnSync)('tmux', ['-V'], { stdio: 'ignore' });
50
+ return result.status === 0;
51
+ }
52
+ exports.TMUX_AVAILABLE = detectTmuxBinary();
53
+ /**
54
+ * v0.5 default is 'headless' — the migration target. Existing users who had
55
+ * tmux working will see the same outputs in the cockpit; only the spawn
56
+ * mechanism differs. To revert, flip the toggle in /settings or set the env
57
+ * override `CHORUS_TRANSPORT=tmux` (env wins over settings — useful for CI
58
+ * and per-user overrides without DB writes).
59
+ */
60
+ exports.DEFAULT_TRANSPORT = 'headless';
61
+ // Module-level dedup so we warn once per process, not once per chat. The
62
+ // daemon reads getTransport() per-chat, and a stuck typo in CHORUS_TRANSPORT
63
+ // would otherwise spam stderr for every new chat.
64
+ let envWarnFired = false;
65
+ async function getTransport() {
66
+ // Env override takes precedence — operator escape hatch.
67
+ const envOverride = process.env.CHORUS_TRANSPORT;
68
+ let resolved;
69
+ if (envOverride === 'headless' || envOverride === 'tmux') {
70
+ resolved = envOverride;
71
+ }
72
+ else {
73
+ if (envOverride !== undefined && envOverride !== '' && !envWarnFired) {
74
+ // Operator-typo aid: silent fallback used to mean a misspelled
75
+ // CHORUS_TRANSPORT (e.g. "headles") just inherited DB/default with no
76
+ // signal. Surface once on stderr; one line, no stack, no rotation.
77
+ console.warn(`[chorus] CHORUS_TRANSPORT=${JSON.stringify(envOverride)} is not 'headless' or 'tmux' — ignoring env, falling back to settings/default.`);
78
+ envWarnFired = true;
79
+ }
80
+ const raw = await db_1.settings.get(TRANSPORT_KEY);
81
+ const parsed = TransportSchema.safeParse(raw);
82
+ resolved = parsed.success ? parsed.data : exports.DEFAULT_TRANSPORT;
83
+ }
84
+ // Cross-platform safety net — see TMUX_AVAILABLE doc.
85
+ if (resolved === 'tmux' && !exports.TMUX_AVAILABLE)
86
+ return 'headless';
87
+ return resolved;
88
+ }
89
+ async function setTransport(value) {
90
+ TransportSchema.parse(value);
91
+ if (value === 'tmux' && !exports.TMUX_AVAILABLE) {
92
+ if ((0, os_1.platform)() === 'win32') {
93
+ throw new Error('tmux transport is not available on Windows — headless transport works for everything tmux does plus more.');
94
+ }
95
+ throw new Error('tmux is not installed on this host. Install it first (macOS: `brew install tmux` · Ubuntu/Debian: `sudo apt install tmux` · Fedora/RHEL: `sudo dnf install tmux`), then restart the chorus daemon and try again.');
96
+ }
97
+ await db_1.settings.set(TRANSPORT_KEY, value);
98
+ return getTransport();
99
+ }
100
+ /**
101
+ * Human-readable description for the /settings UI toggle.
102
+ */
103
+ exports.TRANSPORT_DESCRIPTIONS = {
104
+ headless: {
105
+ label: 'Headless (faster, default)',
106
+ description: 'Each CLI runs as a one-shot subprocess. ~80% less RAM, faster cold start, no permission dialogs. Recommended for everyday use.',
107
+ },
108
+ tmux: {
109
+ label: 'Tmux — attach & take over',
110
+ description: 'Each CLI runs in a persistent tmux session you can attach to (`tmux attach -t <name>`) to watch step-by-step or take over mid-run. Uses more RAM. Requires tmux installed on the host (brew/apt/dnf).',
111
+ },
112
+ };
113
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../../src/lib/settings/transport.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AA+CH,oCAuBC;AAED,oCAcC;AApFD,8BAAiC;AACjC,6BAAwB;AACxB,2BAA8B;AAC9B,iDAA0C;AAI1C,MAAM,eAAe,GAAG,OAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;AAErD,MAAM,aAAa,GAAG,WAAW,CAAC;AAElC;;;;;;;;;;;GAWG;AACH,SAAS,gBAAgB;IACvB,IAAI,IAAA,aAAQ,GAAE,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC;AAC7B,CAAC;AAEY,QAAA,cAAc,GAAY,gBAAgB,EAAE,CAAC;AAE1D;;;;;;GAMG;AACU,QAAA,iBAAiB,GAAc,UAAU,CAAC;AAEvD,yEAAyE;AACzE,6EAA6E;AAC7E,kDAAkD;AAClD,IAAI,YAAY,GAAG,KAAK,CAAC;AAElB,KAAK,UAAU,YAAY;IAChC,yDAAyD;IACzD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACjD,IAAI,QAAmB,CAAC;IACxB,IAAI,WAAW,KAAK,UAAU,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;QACzD,QAAQ,GAAG,WAAW,CAAC;IACzB,CAAC;SAAM,CAAC;QACN,IAAI,WAAW,KAAK,SAAS,IAAI,WAAW,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC;YACrE,+DAA+D;YAC/D,sEAAsE;YACtE,mEAAmE;YACnE,OAAO,CAAC,IAAI,CACV,6BAA6B,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,gFAAgF,CACzI,CAAC;YACF,YAAY,GAAG,IAAI,CAAC;QACtB,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,aAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9C,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,yBAAiB,CAAC;IAC9D,CAAC;IACD,sDAAsD;IACtD,IAAI,QAAQ,KAAK,MAAM,IAAI,CAAC,sBAAc;QAAE,OAAO,UAAU,CAAC;IAC9D,OAAO,QAAQ,CAAC;AAClB,CAAC;AAEM,KAAK,UAAU,YAAY,CAAC,KAAgB;IACjD,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,IAAI,KAAK,KAAK,MAAM,IAAI,CAAC,sBAAc,EAAE,CAAC;QACxC,IAAI,IAAA,aAAQ,GAAE,KAAK,OAAO,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,2GAA2G,CAC5G,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,KAAK,CACb,kNAAkN,CACnN,CAAC;IACJ,CAAC;IACD,MAAM,aAAQ,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACzC,OAAO,YAAY,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACU,QAAA,sBAAsB,GAA8D;IAC/F,QAAQ,EAAE;QACR,KAAK,EAAE,4BAA4B;QACnC,WAAW,EACT,gIAAgI;KACnI;IACD,IAAI,EAAE;QACJ,KAAK,EAAE,2BAA2B;QAClC,WAAW,EACT,uMAAuM;KAC1M;CACF,CAAC"}