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.
- package/.next/BUILD_ID +1 -1
- package/.next/build-manifest.json +3 -3
- package/.next/cache/.previewinfo +1 -1
- package/.next/cache/.rscinfo +1 -1
- package/.next/fallback-build-manifest.json +3 -3
- package/.next/prerender-manifest.json +3 -3
- package/.next/server/app/_global-error.html +1 -1
- package/.next/server/app/_global-error.rsc +1 -1
- package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/_not-found.html +1 -1
- package/.next/server/app/_not-found.rsc +1 -1
- package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/new.html +1 -1
- package/.next/server/app/new.rsc +1 -1
- package/.next/server/app/new.segments/_full.segment.rsc +1 -1
- package/.next/server/app/new.segments/_head.segment.rsc +1 -1
- package/.next/server/app/new.segments/_index.segment.rsc +1 -1
- package/.next/server/app/new.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/new.segments/new/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/new.segments/new.segment.rsc +1 -1
- package/.next/server/app/onboarding.html +1 -1
- package/.next/server/app/onboarding.rsc +1 -1
- package/.next/server/app/onboarding.segments/_full.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_head.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_index.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/onboarding/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/onboarding.segments/onboarding.segment.rsc +1 -1
- package/.next/server/app/personas.html +1 -1
- package/.next/server/app/personas.rsc +1 -1
- package/.next/server/app/personas.segments/_full.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_head.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_index.segment.rsc +1 -1
- package/.next/server/app/personas.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/personas.segments/personas/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/personas.segments/personas.segment.rsc +1 -1
- package/.next/server/app/settings.html +1 -1
- package/.next/server/app/settings.rsc +1 -1
- package/.next/server/app/settings.segments/_full.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_head.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_index.segment.rsc +1 -1
- package/.next/server/app/settings.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/settings.segments/settings.segment.rsc +1 -1
- package/.next/server/app/templates.html +1 -1
- package/.next/server/app/templates.rsc +1 -1
- package/.next/server/app/templates.segments/_full.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_head.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_index.segment.rsc +1 -1
- package/.next/server/app/templates.segments/_tree.segment.rsc +1 -1
- package/.next/server/app/templates.segments/templates/__PAGE__.segment.rsc +1 -1
- package/.next/server/app/templates.segments/templates.segment.rsc +1 -1
- package/.next/server/middleware-build-manifest.js +3 -3
- package/.next/server/pages/404.html +1 -1
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.js +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/trace +1 -1
- package/.next/trace-build +1 -1
- package/dist/cli/commands/doctor.js +116 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/init.js +211 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/start.js +240 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/status.js +54 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/stop.js +97 -0
- package/dist/cli/commands/stop.js.map +1 -0
- package/dist/cli/connect.js +108 -0
- package/dist/cli/connect.js.map +1 -0
- package/dist/cli/index.js +99 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/port-utils.js +260 -0
- package/dist/cli/port-utils.js.map +1 -0
- package/dist/cli/runtime-env.js +60 -0
- package/dist/cli/runtime-env.js.map +1 -0
- package/dist/cli/shared.js +54 -0
- package/dist/cli/shared.js.map +1 -0
- package/dist/cli/ui.js +60 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/daemon/agents/claude.js +98 -0
- package/dist/daemon/agents/claude.js.map +1 -0
- package/dist/daemon/agents/codex.js +160 -0
- package/dist/daemon/agents/codex.js.map +1 -0
- package/dist/daemon/agents/gemini.js +111 -0
- package/dist/daemon/agents/gemini.js.map +1 -0
- package/dist/daemon/agents/index.js +59 -0
- package/dist/daemon/agents/index.js.map +1 -0
- package/dist/daemon/agents/kimi.js +206 -0
- package/dist/daemon/agents/kimi.js.map +1 -0
- package/dist/daemon/agents/opencode.js +228 -0
- package/dist/daemon/agents/opencode.js.map +1 -0
- package/dist/daemon/agents/openrouter.js +274 -0
- package/dist/daemon/agents/openrouter.js.map +1 -0
- package/dist/daemon/agents/parsers/claude.js +63 -0
- package/dist/daemon/agents/parsers/claude.js.map +1 -0
- package/dist/daemon/agents/parsers/codex.js +51 -0
- package/dist/daemon/agents/parsers/codex.js.map +1 -0
- package/dist/daemon/agents/parsers/gemini.js +144 -0
- package/dist/daemon/agents/parsers/gemini.js.map +1 -0
- package/dist/daemon/agents/parsers/index.js +31 -0
- package/dist/daemon/agents/parsers/index.js.map +1 -0
- package/dist/daemon/agents/parsers/kimi.js +8 -0
- package/dist/daemon/agents/parsers/kimi.js.map +1 -0
- package/dist/daemon/agents/parsers/opencode.js +105 -0
- package/dist/daemon/agents/parsers/opencode.js.map +1 -0
- package/dist/daemon/agents/parsers/openrouter.js +69 -0
- package/dist/daemon/agents/parsers/openrouter.js.map +1 -0
- package/dist/daemon/agents/parsers/shared.js +17 -0
- package/dist/daemon/agents/parsers/shared.js.map +1 -0
- package/dist/daemon/agents/preflight.js +83 -0
- package/dist/daemon/agents/preflight.js.map +1 -0
- package/dist/daemon/agents/quote.js +45 -0
- package/dist/daemon/agents/quote.js.map +1 -0
- package/dist/daemon/agents/sandbox-guard.js +69 -0
- package/dist/daemon/agents/sandbox-guard.js.map +1 -0
- package/dist/daemon/agents/types.js +6 -0
- package/dist/daemon/agents/types.js.map +1 -0
- package/dist/daemon/api-response.js +65 -0
- package/dist/daemon/api-response.js.map +1 -0
- package/dist/daemon/error-detector.js +329 -0
- package/dist/daemon/error-detector.js.map +1 -0
- package/dist/daemon/headless.js +533 -0
- package/dist/daemon/headless.js.map +1 -0
- package/dist/daemon/index.js +333 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/openrouter.js +192 -0
- package/dist/daemon/openrouter.js.map +1 -0
- package/dist/daemon/orchestrators/claude.js +163 -0
- package/dist/daemon/orchestrators/claude.js.map +1 -0
- package/dist/daemon/orchestrators/codex.js +101 -0
- package/dist/daemon/orchestrators/codex.js.map +1 -0
- package/dist/daemon/orchestrators/cursor-windsurf.js +118 -0
- package/dist/daemon/orchestrators/cursor-windsurf.js.map +1 -0
- package/dist/daemon/orchestrators/gemini.js +108 -0
- package/dist/daemon/orchestrators/gemini.js.map +1 -0
- package/dist/daemon/orchestrators/index.js +90 -0
- package/dist/daemon/orchestrators/index.js.map +1 -0
- package/dist/daemon/orchestrators/kimi.js +108 -0
- package/dist/daemon/orchestrators/kimi.js.map +1 -0
- package/dist/daemon/orchestrators/opencode.js +152 -0
- package/dist/daemon/orchestrators/opencode.js.map +1 -0
- package/dist/daemon/orchestrators/shared.js +60 -0
- package/dist/daemon/orchestrators/shared.js.map +1 -0
- package/dist/daemon/output-watcher.js +131 -0
- package/dist/daemon/output-watcher.js.map +1 -0
- package/dist/daemon/participant-aborts.js +123 -0
- package/dist/daemon/participant-aborts.js.map +1 -0
- package/dist/daemon/reaper.js +46 -0
- package/dist/daemon/reaper.js.map +1 -0
- package/dist/daemon/routes/chats-events.js +62 -0
- package/dist/daemon/routes/chats-events.js.map +1 -0
- package/dist/daemon/routes/chats-stream.js +241 -0
- package/dist/daemon/routes/chats-stream.js.map +1 -0
- package/dist/daemon/routes/chats-validation.js +13 -0
- package/dist/daemon/routes/chats-validation.js.map +1 -0
- package/dist/daemon/routes/chats.js +545 -0
- package/dist/daemon/routes/chats.js.map +1 -0
- package/dist/daemon/routes/openrouter.js +103 -0
- package/dist/daemon/routes/openrouter.js.map +1 -0
- package/dist/daemon/routes/settings.js +199 -0
- package/dist/daemon/routes/settings.js.map +1 -0
- package/dist/daemon/routes/stats.js +155 -0
- package/dist/daemon/routes/stats.js.map +1 -0
- package/dist/daemon/routes/system.js +208 -0
- package/dist/daemon/routes/system.js.map +1 -0
- package/dist/daemon/routes/templates-personas.js +254 -0
- package/dist/daemon/routes/templates-personas.js.map +1 -0
- package/dist/daemon/routes/voices.js +139 -0
- package/dist/daemon/routes/voices.js.map +1 -0
- package/dist/daemon/runner/doer-driver.js +346 -0
- package/dist/daemon/runner/doer-driver.js.map +1 -0
- package/dist/daemon/runner/doer.js +336 -0
- package/dist/daemon/runner/doer.js.map +1 -0
- package/dist/daemon/runner/prior-round.js +140 -0
- package/dist/daemon/runner/prior-round.js.map +1 -0
- package/dist/daemon/runner/prompt-builder.js +292 -0
- package/dist/daemon/runner/prompt-builder.js.map +1 -0
- package/dist/daemon/runner/review-only-phase.js +103 -0
- package/dist/daemon/runner/review-only-phase.js.map +1 -0
- package/dist/daemon/runner/reviewer-driver.js +410 -0
- package/dist/daemon/runner/reviewer-driver.js.map +1 -0
- package/dist/daemon/runner/reviewer.js +384 -0
- package/dist/daemon/runner/reviewer.js.map +1 -0
- package/dist/daemon/runner/run-with-fallback.js +56 -0
- package/dist/daemon/runner/run-with-fallback.js.map +1 -0
- package/dist/daemon/runner/sanitize-name.js +8 -0
- package/dist/daemon/runner/sanitize-name.js.map +1 -0
- package/dist/daemon/runner/stream-file-writer.js +116 -0
- package/dist/daemon/runner/stream-file-writer.js.map +1 -0
- package/dist/daemon/runner/swap-sidecar.js +102 -0
- package/dist/daemon/runner/swap-sidecar.js.map +1 -0
- package/dist/daemon/runner/template-fallback.js +119 -0
- package/dist/daemon/runner/template-fallback.js.map +1 -0
- package/dist/daemon/runner/types.js +3 -0
- package/dist/daemon/runner/types.js.map +1 -0
- package/dist/daemon/runner/verdict.js +51 -0
- package/dist/daemon/runner/verdict.js.map +1 -0
- package/dist/daemon/runner-multiplex.js +364 -0
- package/dist/daemon/runner-multiplex.js.map +1 -0
- package/dist/daemon/runner.js +427 -0
- package/dist/daemon/runner.js.map +1 -0
- package/dist/daemon/ship.js +340 -0
- package/dist/daemon/ship.js.map +1 -0
- package/dist/daemon/template-cache.js +37 -0
- package/dist/daemon/template-cache.js.map +1 -0
- package/dist/daemon/tmux-types.js +9 -0
- package/dist/daemon/tmux-types.js.map +1 -0
- package/dist/daemon/tmux.js +341 -0
- package/dist/daemon/tmux.js.map +1 -0
- package/dist/lib/atomic-write.js +55 -0
- package/dist/lib/atomic-write.js.map +1 -0
- package/dist/lib/chat-events-bus.js +27 -0
- package/dist/lib/chat-events-bus.js.map +1 -0
- package/dist/lib/chat-slug.js +105 -0
- package/dist/lib/chat-slug.js.map +1 -0
- package/dist/lib/cli-detect.js +388 -0
- package/dist/lib/cli-detect.js.map +1 -0
- package/dist/lib/cli-health.js +156 -0
- package/dist/lib/cli-health.js.map +1 -0
- package/dist/lib/cli-paths.js +113 -0
- package/dist/lib/cli-paths.js.map +1 -0
- package/dist/lib/cli-precheck.js +141 -0
- package/dist/lib/cli-precheck.js.map +1 -0
- package/dist/lib/db/chats.js +244 -0
- package/dist/lib/db/chats.js.map +1 -0
- package/dist/lib/db/connection.js +254 -0
- package/dist/lib/db/connection.js.map +1 -0
- package/dist/lib/db/index.js +34 -0
- package/dist/lib/db/index.js.map +1 -0
- package/dist/lib/db/personas.js +65 -0
- package/dist/lib/db/personas.js.map +1 -0
- package/dist/lib/db/phase-events.js +172 -0
- package/dist/lib/db/phase-events.js.map +1 -0
- package/dist/lib/db/secrets.js +53 -0
- package/dist/lib/db/secrets.js.map +1 -0
- package/dist/lib/db/settings.js +47 -0
- package/dist/lib/db/settings.js.map +1 -0
- package/dist/lib/db/templates.js +75 -0
- package/dist/lib/db/templates.js.map +1 -0
- package/dist/lib/db/voices.js +184 -0
- package/dist/lib/db/voices.js.map +1 -0
- package/dist/lib/lineage-maps.js +200 -0
- package/dist/lib/lineage-maps.js.map +1 -0
- package/dist/lib/logger.js +186 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/personas.js +117 -0
- package/dist/lib/personas.js.map +1 -0
- package/dist/lib/runtime-path.js +222 -0
- package/dist/lib/runtime-path.js.map +1 -0
- package/dist/lib/settings/billing.js +58 -0
- package/dist/lib/settings/billing.js.map +1 -0
- package/dist/lib/settings/permissions.js +81 -0
- package/dist/lib/settings/permissions.js.map +1 -0
- package/dist/lib/settings/transport.js +113 -0
- package/dist/lib/settings/transport.js.map +1 -0
- package/dist/lib/telemetry.js +290 -0
- package/dist/lib/telemetry.js.map +1 -0
- package/dist/lib/template-schema.js +319 -0
- package/dist/lib/template-schema.js.map +1 -0
- package/dist/lib/template-validation.js +82 -0
- package/dist/lib/template-validation.js.map +1 -0
- package/dist/lib/voices.js +533 -0
- package/dist/lib/voices.js.map +1 -0
- package/dist/mcp/client.js +138 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/index.js +178 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/tools.js +355 -0
- package/dist/mcp/tools.js.map +1 -0
- package/package.json +2 -1
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js +0 -6077
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0beh7rg._.js.map +0 -69
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js +0 -6318
- package/.next/dev/static/chunks/05w9_next_dist_shared_lib_0pjsj.j._.js.map +0 -71
- package/.next/dev/types/cache-life.d.ts +0 -145
- package/.next/dev/types/routes.d.ts +0 -84
- package/.next/dev/types/validator.ts +0 -178
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_buildManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 8H2I8TTPlrKuWCV-SxY5f}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Persistence for user-supplied "I know where the CLI lives" paths.
|
|
4
|
+
*
|
|
5
|
+
* Pre-fix the onboarding `/onboard/validate-cli-path` endpoint validated
|
|
6
|
+
* a custom path and returned `{ found: true, path: ... }` to the cockpit
|
|
7
|
+
* — which only updated React state. The path was never persisted, so:
|
|
8
|
+
*
|
|
9
|
+
* - Next daemon boot: cli-detect ran the bare PATH search and lost the
|
|
10
|
+
* hint entirely. CLIs in non-standard locations stayed undetected.
|
|
11
|
+
* - Reviewer spawns: never saw the path. Same "command not found" we
|
|
12
|
+
* hit in the launch smoke tests.
|
|
13
|
+
*
|
|
14
|
+
* This module closes the loop. The cockpit calls `/onboard/save-cli-path`
|
|
15
|
+
* after validation succeeds; cli-detect.ts honours saved paths first
|
|
16
|
+
* (with `source: 'manual'`); the headless spawn merges each saved path's
|
|
17
|
+
* dirname into the runtime PATH.
|
|
18
|
+
*
|
|
19
|
+
* Storage shape: one settings row per CLI, keyed `cli_paths.<id>`. Value
|
|
20
|
+
* is the absolute path string. We deliberately don't use a dedicated
|
|
21
|
+
* table — the data is sparse, write-rarely, single-string, and lives
|
|
22
|
+
* fine alongside other settings.
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.KNOWN_CLI_IDS = exports.cliPaths = void 0;
|
|
26
|
+
const settings_js_1 = require("./db/settings.js");
|
|
27
|
+
const ALL_CLI_IDS = [
|
|
28
|
+
'claude-code',
|
|
29
|
+
'codex-cli',
|
|
30
|
+
'gemini-cli',
|
|
31
|
+
'opencode-cli',
|
|
32
|
+
'kimi-cli',
|
|
33
|
+
];
|
|
34
|
+
const keyFor = (id) => `cli_paths.${id}`;
|
|
35
|
+
/**
|
|
36
|
+
* Sync read-through cache. cli-detect.ts is synchronous (it's called
|
|
37
|
+
* from many places that pre-date the async refactor) but the source of
|
|
38
|
+
* truth lives in the async `settings` table. Boot calls
|
|
39
|
+
* `refreshManualPathCache()` once to populate; sync callers read via
|
|
40
|
+
* `getCached`. Tests / save endpoint call `refresh` again to invalidate.
|
|
41
|
+
*
|
|
42
|
+
* Empty string in DB = explicit clear; we treat as absent in the cache.
|
|
43
|
+
*/
|
|
44
|
+
const cache = new Map();
|
|
45
|
+
let cacheLoaded = false;
|
|
46
|
+
exports.cliPaths = {
|
|
47
|
+
/** Save (or overwrite) a manual path for a CLI. Caller must validate. */
|
|
48
|
+
async set(id, absolutePath) {
|
|
49
|
+
await settings_js_1.settings.set(keyFor(id), absolutePath);
|
|
50
|
+
cache.set(id, absolutePath);
|
|
51
|
+
cacheLoaded = true;
|
|
52
|
+
},
|
|
53
|
+
async get(id) {
|
|
54
|
+
const raw = await settings_js_1.settings.get(keyFor(id));
|
|
55
|
+
return typeof raw === 'string' && raw.length > 0 ? raw : null;
|
|
56
|
+
},
|
|
57
|
+
async clear(id) {
|
|
58
|
+
// settings has no delete; null-store via empty string + treat empty
|
|
59
|
+
// as absent in `get`. Keeps the table cleanable without a schema add.
|
|
60
|
+
await settings_js_1.settings.set(keyFor(id), '');
|
|
61
|
+
cache.delete(id);
|
|
62
|
+
},
|
|
63
|
+
/** Load every saved manual path. Used by buildRuntimeEnv() and chorus doctor. */
|
|
64
|
+
async listAll() {
|
|
65
|
+
const out = {};
|
|
66
|
+
for (const id of ALL_CLI_IDS) {
|
|
67
|
+
out[id] = await exports.cliPaths.get(id);
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
},
|
|
71
|
+
/**
|
|
72
|
+
* Sync lookup against the in-memory cache. Returns null when the cache
|
|
73
|
+
* hasn't been hydrated yet — caller should treat that as "no manual
|
|
74
|
+
* path" (the worst case is a bare PATH search, same as before this
|
|
75
|
+
* feature shipped).
|
|
76
|
+
*/
|
|
77
|
+
getCached(id) {
|
|
78
|
+
if (!cacheLoaded)
|
|
79
|
+
return null;
|
|
80
|
+
return cache.get(id) ?? null;
|
|
81
|
+
},
|
|
82
|
+
/**
|
|
83
|
+
* List every cached manual path's directory. Drives PATH prepend in
|
|
84
|
+
* runtime-path.ts so even a custom-location binary can be invoked by
|
|
85
|
+
* bare name from a daemon-spawned subprocess.
|
|
86
|
+
*/
|
|
87
|
+
cachedDirs() {
|
|
88
|
+
if (!cacheLoaded)
|
|
89
|
+
return [];
|
|
90
|
+
return Array.from(cache.values()).map((abs) => abs.replace(/\/[^/]+$/, ''));
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* Hydrate the sync cache from settings. Called once at daemon boot;
|
|
94
|
+
* also called by the save/clear endpoints to ensure fresh reads. Safe
|
|
95
|
+
* to call multiple times — wipes and repopulates.
|
|
96
|
+
*/
|
|
97
|
+
async refreshCache() {
|
|
98
|
+
cache.clear();
|
|
99
|
+
for (const id of ALL_CLI_IDS) {
|
|
100
|
+
const raw = await settings_js_1.settings.get(keyFor(id));
|
|
101
|
+
if (typeof raw === 'string' && raw.length > 0)
|
|
102
|
+
cache.set(id, raw);
|
|
103
|
+
}
|
|
104
|
+
cacheLoaded = true;
|
|
105
|
+
},
|
|
106
|
+
/** @internal — for tests that rebuild the DB across cases. */
|
|
107
|
+
_resetCacheForTests() {
|
|
108
|
+
cache.clear();
|
|
109
|
+
cacheLoaded = false;
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
exports.KNOWN_CLI_IDS = ALL_CLI_IDS;
|
|
113
|
+
//# sourceMappingURL=cli-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-paths.js","sourceRoot":"","sources":["../../src/lib/cli-paths.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;;;AAEH,kDAA4C;AAS5C,MAAM,WAAW,GAAqB;IACpC,aAAa;IACb,WAAW;IACX,YAAY;IACZ,cAAc;IACd,UAAU;CACF,CAAC;AAEX,MAAM,MAAM,GAAG,CAAC,EAAS,EAAU,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC;AAExD;;;;;;;;GAQG;AACH,MAAM,KAAK,GAAG,IAAI,GAAG,EAAiB,CAAC;AACvC,IAAI,WAAW,GAAG,KAAK,CAAC;AAEX,QAAA,QAAQ,GAAG;IACtB,yEAAyE;IACzE,KAAK,CAAC,GAAG,CAAC,EAAS,EAAE,YAAoB;QACvC,MAAM,sBAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC;QAC7C,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;QAC5B,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,EAAS;QACjB,MAAM,GAAG,GAAG,MAAM,sBAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3C,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAChE,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,EAAS;QACnB,oEAAoE;QACpE,sEAAsE;QACtE,MAAM,sBAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACnC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACnB,CAAC;IAED,iFAAiF;IACjF,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAAG,EAAkC,CAAC;QAC/C,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,gBAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;OAKG;IACH,SAAS,CAAC,EAAS;QACjB,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACH,UAAU;QACR,IAAI,CAAC,WAAW;YAAE,OAAO,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,YAAY;QAChB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,KAAK,MAAM,EAAE,IAAI,WAAW,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,sBAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;gBAAE,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACpE,CAAC;QACD,WAAW,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,8DAA8D;IAC9D,mBAAmB;QACjB,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;CACF,CAAC;AAEW,QAAA,aAAa,GAAG,WAAW,CAAC"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pre-spawn CLI health check.
|
|
4
|
+
*
|
|
5
|
+
* Runs before each CLI subprocess spawn (doer or reviewer) to short-circuit
|
|
6
|
+
* three classes of doomed runs:
|
|
7
|
+
* 1. Quota already exhausted (cli-health.ts has a recent resetAt in the
|
|
8
|
+
* future). Spawning would just hit the same wall in 5–10 seconds and
|
|
9
|
+
* burn UI time.
|
|
10
|
+
* 2. CLI not logged in / cred file missing. Spawning would emit either a
|
|
11
|
+
* cold_start_timeout or token_refresh_lost from the pane scraper after
|
|
12
|
+
* we already paid the spawn tax (~3-5s for tmux/headless boot).
|
|
13
|
+
* 3. CLI binary not present (handled at boot by `cli-detect`; we just
|
|
14
|
+
* mention it here for completeness — not re-checked per spawn).
|
|
15
|
+
*
|
|
16
|
+
* Deliberately cheap: no network calls. We check filesystem state + the
|
|
17
|
+
* existing health record. A real network probe (ping `/v1/models` with the
|
|
18
|
+
* stored bearer to confirm token validity) is the natural next layer; for
|
|
19
|
+
* v0.7 the file-existence check catches "user logged out 3 days ago" which
|
|
20
|
+
* is the highest-frequency failure mode.
|
|
21
|
+
*
|
|
22
|
+
* Returns:
|
|
23
|
+
* - { ok: true } → proceed with spawn
|
|
24
|
+
* - { ok: false, reason, cta } → skip spawn, runner emits cli_warning
|
|
25
|
+
*/
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.precheckLineage = precheckLineage;
|
|
31
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
32
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
33
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
34
|
+
const cli_health_1 = require("./cli-health");
|
|
35
|
+
/**
|
|
36
|
+
* Per-lineage credential file we treat as "user is logged in." Each CLI
|
|
37
|
+
* stores its OAuth bearer somewhere different; if the file doesn't exist
|
|
38
|
+
* the user almost certainly hasn't run the CLI's login command. False
|
|
39
|
+
* positives are possible (some users move credential dirs via env), so we
|
|
40
|
+
* only fail-closed when the file is *missing or unreadable* — never on
|
|
41
|
+
* shape mismatches inside the file.
|
|
42
|
+
*/
|
|
43
|
+
const CRED_PATHS = {
|
|
44
|
+
anthropic: () => [
|
|
45
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.claude', '.credentials.json'),
|
|
46
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.config', 'anthropic', 'claude.json'),
|
|
47
|
+
],
|
|
48
|
+
openai: () => [
|
|
49
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.codex', 'auth.json'),
|
|
50
|
+
],
|
|
51
|
+
google: () => [
|
|
52
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.gemini', 'oauth_creds.json'),
|
|
53
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.config', 'gemini', 'oauth_creds.json'),
|
|
54
|
+
],
|
|
55
|
+
opencode: () => [
|
|
56
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.opencode', 'auth.json'),
|
|
57
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.local', 'share', 'opencode', 'auth.json'),
|
|
58
|
+
],
|
|
59
|
+
moonshot: () => [
|
|
60
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.kimi', 'auth.json'),
|
|
61
|
+
// OpenCode stores its auth in two places depending on install path. The
|
|
62
|
+
// kimi shim delegates to `opencode --model opencode-go/kimi-k2.6` when
|
|
63
|
+
// the requested model carries the opencode-go/ prefix, so a moonshot
|
|
64
|
+
// voice routed via opencode is actually authed by opencode's creds —
|
|
65
|
+
// not the kimi-cli ones. Both opencode candidates accepted here.
|
|
66
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.opencode', 'auth.json'),
|
|
67
|
+
node_path_1.default.join(node_os_1.default.homedir(), '.local', 'share', 'opencode', 'auth.json'),
|
|
68
|
+
],
|
|
69
|
+
// OpenRouter has no on-disk credential file — its API key lives in
|
|
70
|
+
// the secrets table. The shim itself returns auth_missing when the
|
|
71
|
+
// key is unset, which surfaces the same UX without a file probe.
|
|
72
|
+
openrouter: () => [],
|
|
73
|
+
};
|
|
74
|
+
const LOGIN_HINT = {
|
|
75
|
+
anthropic: 'Run `claude login` in a terminal.',
|
|
76
|
+
openai: 'Run `codex login` in a terminal.',
|
|
77
|
+
google: 'Run `gemini` once interactively to complete OAuth.',
|
|
78
|
+
opencode: 'Run `opencode auth login` in a terminal.',
|
|
79
|
+
moonshot: 'Run `kimi` once interactively, or set up opencode if you use the kimi-via-opencode transport.',
|
|
80
|
+
openrouter: 'Save an OpenRouter API key on the Connect page.',
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Check whether at least one of the candidate credential paths for `lineage`
|
|
84
|
+
* exists and is readable. Existence-only — we don't parse contents (each CLI
|
|
85
|
+
* has its own JSON shape and bearer-refresh lifecycle, neither of which we
|
|
86
|
+
* want to couple to). Readable-but-empty counts as missing.
|
|
87
|
+
*/
|
|
88
|
+
function hasCredFile(lineage) {
|
|
89
|
+
const candidates = CRED_PATHS[lineage]();
|
|
90
|
+
for (const p of candidates) {
|
|
91
|
+
try {
|
|
92
|
+
const stat = node_fs_1.default.statSync(p);
|
|
93
|
+
if (stat.isFile() && stat.size > 0) {
|
|
94
|
+
return { exists: true, tried: candidates };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// ENOENT or perm-denied — try next candidate
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return { exists: false, tried: candidates };
|
|
102
|
+
}
|
|
103
|
+
async function precheckLineage(lineage) {
|
|
104
|
+
// Layer 1: quota state from cli-health (populated reactively when the
|
|
105
|
+
// error-detector observes a quota_exhausted pane). If a previous run
|
|
106
|
+
// tripped the limit and the reset hasn't elapsed, skip the spawn.
|
|
107
|
+
const health = await (0, cli_health_1.getHealth)(lineage);
|
|
108
|
+
if (health.status === 'quota_exhausted') {
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
if (typeof health.resetAt === 'number' && health.resetAt > now) {
|
|
111
|
+
const minsLeft = Math.ceil((health.resetAt - now) / 60_000);
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
reason: 'quota_exhausted',
|
|
115
|
+
message: `${lineage} quota still exhausted (resets in ~${minsLeft} min).`,
|
|
116
|
+
cta: 'Wait for reset, switch account, or disable this voice.',
|
|
117
|
+
resetAt: health.resetAt,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// resetAt missing or already past — fall through and let the spawn try.
|
|
121
|
+
// Stale health markers self-clear when a successful run records 'healthy'.
|
|
122
|
+
}
|
|
123
|
+
// OpenRouter has no on-disk creds — the shim itself errors with
|
|
124
|
+
// auth_missing when the secrets-table key is absent. Skip the file probe.
|
|
125
|
+
if (lineage === 'openrouter') {
|
|
126
|
+
return { ok: true };
|
|
127
|
+
}
|
|
128
|
+
// Layer 2: credential file presence. Cheap, catches "logged out" without
|
|
129
|
+
// paying the spawn tax. See CRED_PATHS for the per-CLI lookups.
|
|
130
|
+
const cred = hasCredFile(lineage);
|
|
131
|
+
if (!cred.exists) {
|
|
132
|
+
return {
|
|
133
|
+
ok: false,
|
|
134
|
+
reason: 'auth_missing',
|
|
135
|
+
message: `${lineage} CLI is not logged in (no credential file found).`,
|
|
136
|
+
cta: LOGIN_HINT[lineage],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
return { ok: true };
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=cli-precheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli-precheck.js","sourceRoot":"","sources":["../../src/lib/cli-precheck.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.chats = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const chat_events_bus_js_1 = require("../chat-events-bus.js");
|
|
6
|
+
const connection_js_1 = require("./connection.js");
|
|
7
|
+
const ChatRowSchema = zod_1.z.object({
|
|
8
|
+
id: zod_1.z.string(),
|
|
9
|
+
/**
|
|
10
|
+
* URL-friendly slug derived from `work` on chat creation. Nullable
|
|
11
|
+
* for legacy rows; the daemon backfills these lazily on first
|
|
12
|
+
* list-load. UNIQUE partial index resolves /runs/<slug> in O(1).
|
|
13
|
+
*/
|
|
14
|
+
slug: zod_1.z.string().nullable().default(null),
|
|
15
|
+
work: zod_1.z.string(),
|
|
16
|
+
template_id: zod_1.z.string(),
|
|
17
|
+
status: zod_1.z.enum([
|
|
18
|
+
'drafting',
|
|
19
|
+
'reviewing',
|
|
20
|
+
'approved',
|
|
21
|
+
'merged',
|
|
22
|
+
'blocked',
|
|
23
|
+
'cancelled',
|
|
24
|
+
'failed',
|
|
25
|
+
'no_review',
|
|
26
|
+
]),
|
|
27
|
+
current_phase_idx: zod_1.z.number().int(),
|
|
28
|
+
yolo: zod_1.z.coerce.boolean().default(false),
|
|
29
|
+
attached_files: zod_1.z.string().nullable(),
|
|
30
|
+
repo_path: zod_1.z.string().nullable().default(null),
|
|
31
|
+
pr_url: zod_1.z.string().nullable().default(null),
|
|
32
|
+
ship_error: zod_1.z.string().nullable().default(null),
|
|
33
|
+
artifact: zod_1.z.string().nullable().default(null),
|
|
34
|
+
verdict: zod_1.z.string().nullable().default(null),
|
|
35
|
+
created_at: zod_1.z.number().int(),
|
|
36
|
+
updated_at: zod_1.z.number().int(),
|
|
37
|
+
finished_at: zod_1.z.number().int().nullable(),
|
|
38
|
+
});
|
|
39
|
+
const CreateChatSchema = zod_1.z.object({
|
|
40
|
+
work: zod_1.z.string(),
|
|
41
|
+
template_id: zod_1.z.string(),
|
|
42
|
+
attached_files: zod_1.z.string().optional(),
|
|
43
|
+
/** Absolute path to user's repo for Ship phase. Optional. */
|
|
44
|
+
repo_path: zod_1.z.string().optional(),
|
|
45
|
+
/** Artifact text for review-only templates. Optional at the DB layer; the
|
|
46
|
+
* chat-create endpoint enforces it when the template requires one. */
|
|
47
|
+
artifact: zod_1.z.string().optional(),
|
|
48
|
+
/** Skip ask-user gates for this run. The runner only honours this on the
|
|
49
|
+
* ship phase today; safe to pass on any chat. */
|
|
50
|
+
yolo: zod_1.z.boolean().optional(),
|
|
51
|
+
});
|
|
52
|
+
exports.chats = {
|
|
53
|
+
async create(input) {
|
|
54
|
+
const db = await (0, connection_js_1.getDb)();
|
|
55
|
+
const validated = CreateChatSchema.parse(input);
|
|
56
|
+
const ulid = (0, connection_js_1.generateUlid)();
|
|
57
|
+
const now = Date.now();
|
|
58
|
+
// Generate a unique URL slug BEFORE insert so the returned row is
|
|
59
|
+
// complete (no second SELECT/UPDATE round trip). The collision check
|
|
60
|
+
// uses chats.slugExists which tolerates an in-flight partner row
|
|
61
|
+
// (same slug requested concurrently) — the UNIQUE index is the
|
|
62
|
+
// authoritative race-loser. Retry loop catches the constraint
|
|
63
|
+
// violation, regenerates the slug, and INSERTs again. Capped at 3
|
|
64
|
+
// attempts: if we can't get a unique slug after 3 collisions there's
|
|
65
|
+
// something structurally wrong (clock skew, slug generator bug);
|
|
66
|
+
// fail loud.
|
|
67
|
+
const { generateChatSlug } = await import('../chat-slug.js');
|
|
68
|
+
const MAX_SLUG_ATTEMPTS = 3;
|
|
69
|
+
for (let attempt = 1; attempt <= MAX_SLUG_ATTEMPTS; attempt++) {
|
|
70
|
+
const slug = await generateChatSlug({
|
|
71
|
+
work: validated.work,
|
|
72
|
+
templateId: validated.template_id,
|
|
73
|
+
existsFn: exports.chats.slugExists,
|
|
74
|
+
});
|
|
75
|
+
try {
|
|
76
|
+
await db.execute({
|
|
77
|
+
sql: `
|
|
78
|
+
INSERT INTO chats (id, slug, work, template_id, status, current_phase_idx, yolo, attached_files, repo_path, artifact, created_at, updated_at)
|
|
79
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
80
|
+
`,
|
|
81
|
+
args: [
|
|
82
|
+
ulid,
|
|
83
|
+
slug,
|
|
84
|
+
validated.work,
|
|
85
|
+
validated.template_id,
|
|
86
|
+
'drafting',
|
|
87
|
+
0,
|
|
88
|
+
validated.yolo ? 1 : 0,
|
|
89
|
+
validated.attached_files || null,
|
|
90
|
+
validated.repo_path || null,
|
|
91
|
+
validated.artifact || null,
|
|
92
|
+
now,
|
|
93
|
+
now,
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
const row = await exports.chats.getById(ulid);
|
|
97
|
+
if (!row)
|
|
98
|
+
throw new Error(`chats.create: row vanished after insert: ${ulid}`);
|
|
99
|
+
chat_events_bus_js_1.chatEventsBus.emitChange(row.id, 'created');
|
|
100
|
+
return row;
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
// libsql surfaces UNIQUE violations as Error with message
|
|
104
|
+
// containing "UNIQUE constraint failed: ...idx_chats_slug" (the
|
|
105
|
+
// partial-index name). Retry on this exact pattern; rethrow
|
|
106
|
+
// anything else (FK violations, type errors, conn drops).
|
|
107
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
108
|
+
const isSlugCollision = /UNIQUE constraint failed.*chats\.slug|idx_chats_slug/i.test(message);
|
|
109
|
+
if (!isSlugCollision || attempt === MAX_SLUG_ATTEMPTS)
|
|
110
|
+
throw err;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Unreachable — the loop above either returns or throws on the final attempt.
|
|
114
|
+
throw new Error('chats.create: unique slug allocation failed after retries');
|
|
115
|
+
},
|
|
116
|
+
/** Used by generateChatSlug — does any chat already use this slug? */
|
|
117
|
+
async slugExists(slug) {
|
|
118
|
+
const db = await (0, connection_js_1.getDb)();
|
|
119
|
+
const result = await db.execute({
|
|
120
|
+
sql: 'SELECT 1 FROM chats WHERE slug = ? LIMIT 1',
|
|
121
|
+
args: [slug],
|
|
122
|
+
});
|
|
123
|
+
return result.rows.length > 0;
|
|
124
|
+
},
|
|
125
|
+
async getBySlug(slug) {
|
|
126
|
+
const db = await (0, connection_js_1.getDb)();
|
|
127
|
+
const result = await db.execute({
|
|
128
|
+
sql: 'SELECT * FROM chats WHERE slug = ?',
|
|
129
|
+
args: [slug],
|
|
130
|
+
});
|
|
131
|
+
if (result.rows.length === 0)
|
|
132
|
+
return null;
|
|
133
|
+
return ChatRowSchema.parse(result.rows[0]);
|
|
134
|
+
},
|
|
135
|
+
/**
|
|
136
|
+
* Resolve by slug OR id. Falls back to id lookup when the slug query
|
|
137
|
+
* misses, so legacy URLs (`/runs/<ULID>`) keep working forever.
|
|
138
|
+
*/
|
|
139
|
+
async getBySlugOrId(slugOrId) {
|
|
140
|
+
const { looksLikeSlug } = await import('../chat-slug.js');
|
|
141
|
+
if (looksLikeSlug(slugOrId)) {
|
|
142
|
+
const bySlug = await exports.chats.getBySlug(slugOrId);
|
|
143
|
+
if (bySlug)
|
|
144
|
+
return bySlug;
|
|
145
|
+
}
|
|
146
|
+
return exports.chats.getById(slugOrId);
|
|
147
|
+
},
|
|
148
|
+
async list(opts) {
|
|
149
|
+
const db = await (0, connection_js_1.getDb)();
|
|
150
|
+
let sql = 'SELECT * FROM chats';
|
|
151
|
+
const args = [];
|
|
152
|
+
if (opts?.status) {
|
|
153
|
+
sql += ' WHERE status = ?';
|
|
154
|
+
args.push(opts.status);
|
|
155
|
+
}
|
|
156
|
+
sql += ' ORDER BY updated_at DESC';
|
|
157
|
+
if (opts?.limit) {
|
|
158
|
+
sql += ' LIMIT ?';
|
|
159
|
+
args.push(opts.limit);
|
|
160
|
+
}
|
|
161
|
+
if (opts?.offset) {
|
|
162
|
+
sql += ' OFFSET ?';
|
|
163
|
+
args.push(opts.offset);
|
|
164
|
+
}
|
|
165
|
+
const result = await db.execute({ sql, args: args });
|
|
166
|
+
return result.rows.map((row) => ChatRowSchema.parse(row));
|
|
167
|
+
},
|
|
168
|
+
async getById(id) {
|
|
169
|
+
const db = await (0, connection_js_1.getDb)();
|
|
170
|
+
const result = await db.execute({ sql: 'SELECT * FROM chats WHERE id = ?', args: [id] });
|
|
171
|
+
if (result.rows.length === 0)
|
|
172
|
+
return null;
|
|
173
|
+
return ChatRowSchema.parse(result.rows[0]);
|
|
174
|
+
},
|
|
175
|
+
async update(id, partial) {
|
|
176
|
+
const db = await (0, connection_js_1.getDb)();
|
|
177
|
+
const chat = await exports.chats.getById(id);
|
|
178
|
+
if (!chat) {
|
|
179
|
+
throw new Error(`Chat ${id} not found`);
|
|
180
|
+
}
|
|
181
|
+
const updated = {
|
|
182
|
+
...chat,
|
|
183
|
+
...partial,
|
|
184
|
+
id: chat.id,
|
|
185
|
+
created_at: chat.created_at,
|
|
186
|
+
updated_at: Date.now(),
|
|
187
|
+
};
|
|
188
|
+
await db.execute({
|
|
189
|
+
sql: `
|
|
190
|
+
UPDATE chats
|
|
191
|
+
SET work = ?, template_id = ?, status = ?, current_phase_idx = ?, yolo = ?, attached_files = ?, repo_path = ?, pr_url = ?, ship_error = ?, artifact = ?, verdict = ?, updated_at = ?, finished_at = ?
|
|
192
|
+
WHERE id = ?
|
|
193
|
+
`,
|
|
194
|
+
args: [
|
|
195
|
+
updated.work,
|
|
196
|
+
updated.template_id,
|
|
197
|
+
updated.status,
|
|
198
|
+
updated.current_phase_idx,
|
|
199
|
+
updated.yolo ? 1 : 0,
|
|
200
|
+
updated.attached_files,
|
|
201
|
+
updated.repo_path,
|
|
202
|
+
updated.pr_url,
|
|
203
|
+
updated.ship_error,
|
|
204
|
+
updated.artifact,
|
|
205
|
+
updated.verdict,
|
|
206
|
+
updated.updated_at,
|
|
207
|
+
updated.finished_at,
|
|
208
|
+
id,
|
|
209
|
+
],
|
|
210
|
+
});
|
|
211
|
+
const row = await exports.chats.getById(id);
|
|
212
|
+
if (!row)
|
|
213
|
+
throw new Error(`chats.update: row vanished: ${id}`);
|
|
214
|
+
chat_events_bus_js_1.chatEventsBus.emitChange(row.id, 'updated');
|
|
215
|
+
return row;
|
|
216
|
+
},
|
|
217
|
+
async cancel(id) {
|
|
218
|
+
return exports.chats.update(id, { status: 'cancelled', finished_at: Date.now() });
|
|
219
|
+
},
|
|
220
|
+
/**
|
|
221
|
+
* Hard-delete a chat. Removes the row + cascades to phase_events.
|
|
222
|
+
* Atomic via libsql transaction so a partial failure can't leave
|
|
223
|
+
* orphaned phase_events. Caller is responsible for filesystem cleanup
|
|
224
|
+
* (chat artifacts in ~/.chorus/chats/<id>) and for ensuring no active
|
|
225
|
+
* session is running (cancel first if needed).
|
|
226
|
+
*/
|
|
227
|
+
async delete(id) {
|
|
228
|
+
const db = await (0, connection_js_1.getDb)();
|
|
229
|
+
const tx = await db.transaction('write');
|
|
230
|
+
try {
|
|
231
|
+
// Phase events first to avoid orphans (no FK enforcement, but the
|
|
232
|
+
// chat semantically owns its events).
|
|
233
|
+
await tx.execute({ sql: 'DELETE FROM phase_events WHERE chat_id = ?', args: [id] });
|
|
234
|
+
await tx.execute({ sql: 'DELETE FROM chats WHERE id = ?', args: [id] });
|
|
235
|
+
await tx.commit();
|
|
236
|
+
chat_events_bus_js_1.chatEventsBus.emitChange(id, 'deleted');
|
|
237
|
+
}
|
|
238
|
+
catch (e) {
|
|
239
|
+
await tx.rollback();
|
|
240
|
+
throw e;
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
//# sourceMappingURL=chats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chats.js","sourceRoot":"","sources":["../../../src/lib/db/chats.ts"],"names":[],"mappings":"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"}
|