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.
- 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/cache/.tsbuildinfo +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/README.md +38 -15
- 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 +298 -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 → 9cD3yIOGe_Aqr17uJHTQS}/_buildManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{dJlbRLlhISA0JGtHKVqgQ → 9cD3yIOGe_Aqr17uJHTQS}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Chorus DB seam — backed by @libsql/client (napi-rs prebuilt for every
|
|
4
|
+
* platform; no node-gyp at install time). Migrated from better-sqlite3 in
|
|
5
|
+
* v0.7 to fix `npm install -g` reliability on Windows + locked-down dev
|
|
6
|
+
* machines (planning/libsql-migration.md).
|
|
7
|
+
*
|
|
8
|
+
* SQL dialect + on-disk format are unchanged — same SQLite3 file at
|
|
9
|
+
* ~/.chorus/chorus.db. Existing user DBs open cleanly.
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.resolveDbPath = resolveDbPath;
|
|
16
|
+
exports.getDb = getDb;
|
|
17
|
+
exports._resetDbForTests = _resetDbForTests;
|
|
18
|
+
exports.generateUlid = generateUlid;
|
|
19
|
+
const client_1 = require("@libsql/client");
|
|
20
|
+
const fs_1 = require("fs");
|
|
21
|
+
const fs_2 = __importDefault(require("fs"));
|
|
22
|
+
const os_1 = __importDefault(require("os"));
|
|
23
|
+
const path_1 = __importDefault(require("path"));
|
|
24
|
+
let dbInstance = null;
|
|
25
|
+
let dbInitPromise = null;
|
|
26
|
+
/**
|
|
27
|
+
* Resolve DB path lazily inside getDb() rather than at module load. Two
|
|
28
|
+
* reasons:
|
|
29
|
+
* 1. CHORUS_DB_PATH env override only takes effect if read at init time.
|
|
30
|
+
* A module-level `const dbPath = ...` evaluates once on import and is
|
|
31
|
+
* then frozen, so tests setting the env after import would have no
|
|
32
|
+
* effect.
|
|
33
|
+
* 2. Tests need to swap DBs between cases without restarting the
|
|
34
|
+
* process — see `_resetDbForTests()`.
|
|
35
|
+
*/
|
|
36
|
+
function resolveDbPath() {
|
|
37
|
+
const override = process.env.CHORUS_DB_PATH;
|
|
38
|
+
if (override)
|
|
39
|
+
return override;
|
|
40
|
+
return path_1.default.join(os_1.default.homedir(), '.chorus', 'chorus.db');
|
|
41
|
+
}
|
|
42
|
+
function resolveSchemaPath() {
|
|
43
|
+
// dist/lib/db/connection.js needs ../db/schema.sql; src/lib/db/
|
|
44
|
+
// connection.ts in tsx-watch dev mode resolves the same way. build:server
|
|
45
|
+
// copies the .sql alongside the compiled .js (see package.json).
|
|
46
|
+
return path_1.default.join(__dirname, '..', 'db', 'schema.sql');
|
|
47
|
+
}
|
|
48
|
+
async function getDb() {
|
|
49
|
+
if (dbInstance)
|
|
50
|
+
return dbInstance;
|
|
51
|
+
if (dbInitPromise)
|
|
52
|
+
return dbInitPromise;
|
|
53
|
+
dbInitPromise = initDb()
|
|
54
|
+
.then((db) => {
|
|
55
|
+
dbInstance = db;
|
|
56
|
+
return db;
|
|
57
|
+
})
|
|
58
|
+
.catch((err) => {
|
|
59
|
+
// CRITICAL: clear the cached promise on failure. Without this, a
|
|
60
|
+
// single transient init error (corrupted DB, FS hiccup, permission
|
|
61
|
+
// glitch) would lock the daemon forever — every subsequent getDb()
|
|
62
|
+
// call would return the same rejected promise until restart.
|
|
63
|
+
dbInitPromise = null;
|
|
64
|
+
throw err;
|
|
65
|
+
});
|
|
66
|
+
return dbInitPromise;
|
|
67
|
+
}
|
|
68
|
+
async function initDb() {
|
|
69
|
+
const dbPath = resolveDbPath();
|
|
70
|
+
const dbDir = path_1.default.dirname(dbPath);
|
|
71
|
+
if (!fs_2.default.existsSync(dbDir)) {
|
|
72
|
+
// 0700: only the owner traverses ~/.chorus. Without this the dir
|
|
73
|
+
// inherits umask (typically 0755 → world-traversable), which lets
|
|
74
|
+
// other local users `cat ~/.chorus/chorus.db` and read every API
|
|
75
|
+
// key in the secrets table. Audit A2 BLOCKER.
|
|
76
|
+
fs_2.default.mkdirSync(dbDir, { recursive: true, mode: 0o700 });
|
|
77
|
+
}
|
|
78
|
+
else if (path_1.default.basename(dbDir) === '.chorus') {
|
|
79
|
+
// Existing ~/.chorus from before this fix shipped — tighten
|
|
80
|
+
// retroactively on first boot of an upgraded install. Guard on the
|
|
81
|
+
// dirname so a CHORUS_DB_PATH override pointing at a system dir
|
|
82
|
+
// (e.g. tests using /tmp/chorus-foo.db) doesn't chmod /tmp to 0700.
|
|
83
|
+
// Best-effort; failure on exotic filesystems is non-fatal.
|
|
84
|
+
try {
|
|
85
|
+
fs_2.default.chmodSync(dbDir, 0o700);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
/* non-fatal */
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const isNew = !fs_2.default.existsSync(dbPath);
|
|
92
|
+
const db = (0, client_1.createClient)({ url: `file:${dbPath}` });
|
|
93
|
+
// Lock down the SQLite file (and WAL/SHM sidecars when they appear)
|
|
94
|
+
// to owner-only read/write. Best-effort on every boot — covers fresh
|
|
95
|
+
// creation, retroactive hardening, and the case where a sidecar was
|
|
96
|
+
// recreated by libsql with default umask after a rare crash.
|
|
97
|
+
for (const f of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`, `${dbPath}-journal`]) {
|
|
98
|
+
try {
|
|
99
|
+
if (fs_2.default.existsSync(f))
|
|
100
|
+
fs_2.default.chmodSync(f, 0o600);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
/* non-fatal */
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// libsql defaults to WAL on local file URLs. Setting it explicitly
|
|
107
|
+
// keeps the intent visible in code reviews; no-op if already WAL.
|
|
108
|
+
await db.execute('PRAGMA journal_mode = WAL');
|
|
109
|
+
// PRAGMA journal_mode=WAL creates the -wal/-shm sidecars if they
|
|
110
|
+
// didn't already exist. Re-chmod now so a brand-new DB never lives
|
|
111
|
+
// even briefly with default-umask permissions on the WAL file.
|
|
112
|
+
// Round-tripping the chmod loop is cheaper than risking a fast
|
|
113
|
+
// attacker who can read the WAL between init and first write.
|
|
114
|
+
for (const f of [`${dbPath}-wal`, `${dbPath}-shm`]) {
|
|
115
|
+
try {
|
|
116
|
+
if (fs_2.default.existsSync(f))
|
|
117
|
+
fs_2.default.chmodSync(f, 0o600);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
/* non-fatal */
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (isNew) {
|
|
124
|
+
const schema = (0, fs_1.readFileSync)(resolveSchemaPath(), 'utf-8');
|
|
125
|
+
await db.executeMultiple(schema);
|
|
126
|
+
}
|
|
127
|
+
// Run idempotent column-add migrations on every startup, not just for
|
|
128
|
+
// existing DBs. A fresh DB created from a stale dist/schema.sql (e.g.
|
|
129
|
+
// when the build script forgot to copy the latest schema) would
|
|
130
|
+
// otherwise skip these and crash on first INSERT.
|
|
131
|
+
const cols = (await db.execute('PRAGMA table_info(chats)')).rows;
|
|
132
|
+
const has = (n) => cols.some((c) => c.name === n);
|
|
133
|
+
if (!has('repo_path'))
|
|
134
|
+
await db.execute('ALTER TABLE chats ADD COLUMN repo_path TEXT');
|
|
135
|
+
if (!has('pr_url'))
|
|
136
|
+
await db.execute('ALTER TABLE chats ADD COLUMN pr_url TEXT');
|
|
137
|
+
if (!has('ship_error'))
|
|
138
|
+
await db.execute('ALTER TABLE chats ADD COLUMN ship_error TEXT');
|
|
139
|
+
if (!has('artifact'))
|
|
140
|
+
await db.execute('ALTER TABLE chats ADD COLUMN artifact TEXT');
|
|
141
|
+
if (!has('verdict'))
|
|
142
|
+
await db.execute('ALTER TABLE chats ADD COLUMN verdict TEXT');
|
|
143
|
+
// Nullable for legacy rows; backfilled on first list-load. UNIQUE
|
|
144
|
+
// partial index lets us resolve /runs/<slug> in O(1).
|
|
145
|
+
if (!has('slug'))
|
|
146
|
+
await db.execute('ALTER TABLE chats ADD COLUMN slug TEXT');
|
|
147
|
+
await db.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_chats_slug ON chats(slug) WHERE slug IS NOT NULL');
|
|
148
|
+
await backfillChatSlugs(db);
|
|
149
|
+
// Personas — added in v0.7. Idempotent CREATE so DBs that pre-date
|
|
150
|
+
// this version pick it up without a manual migration.
|
|
151
|
+
await db.execute(`
|
|
152
|
+
CREATE TABLE IF NOT EXISTS personas (
|
|
153
|
+
id TEXT PRIMARY KEY,
|
|
154
|
+
label TEXT NOT NULL,
|
|
155
|
+
one_liner TEXT NOT NULL,
|
|
156
|
+
system_prompt TEXT NOT NULL,
|
|
157
|
+
recommended_lineage TEXT,
|
|
158
|
+
builtin INTEGER NOT NULL DEFAULT 0,
|
|
159
|
+
forked_from TEXT,
|
|
160
|
+
created_at INTEGER NOT NULL,
|
|
161
|
+
updated_at INTEGER NOT NULL
|
|
162
|
+
)
|
|
163
|
+
`);
|
|
164
|
+
// Voices — added in v0.7 (planning/voices.md).
|
|
165
|
+
await db.execute(`
|
|
166
|
+
CREATE TABLE IF NOT EXISTS voices (
|
|
167
|
+
id TEXT PRIMARY KEY,
|
|
168
|
+
label TEXT NOT NULL,
|
|
169
|
+
source TEXT NOT NULL,
|
|
170
|
+
provider TEXT NOT NULL,
|
|
171
|
+
model_id TEXT NOT NULL,
|
|
172
|
+
lineage TEXT NOT NULL,
|
|
173
|
+
vendor_family TEXT,
|
|
174
|
+
input_cost_per_mtok REAL,
|
|
175
|
+
output_cost_per_mtok REAL,
|
|
176
|
+
enabled INTEGER NOT NULL DEFAULT 1,
|
|
177
|
+
created_at INTEGER NOT NULL,
|
|
178
|
+
updated_at INTEGER NOT NULL
|
|
179
|
+
)
|
|
180
|
+
`);
|
|
181
|
+
await db.execute('CREATE INDEX IF NOT EXISTS idx_voices_lineage ON voices(lineage)');
|
|
182
|
+
await db.execute('CREATE INDEX IF NOT EXISTS idx_voices_provider ON voices(provider)');
|
|
183
|
+
await db.execute('CREATE INDEX IF NOT EXISTS idx_voices_source ON voices(source)');
|
|
184
|
+
// disabled_reason — added so the seed can distinguish user-intent toggles
|
|
185
|
+
// from transient auto-disables on missed CLI detection. Without this the
|
|
186
|
+
// re-detect path can't safely re-enable rows; one flaky boot would leave
|
|
187
|
+
// a voice silently disabled forever.
|
|
188
|
+
const voiceCols = (await db.execute('PRAGMA table_info(voices)')).rows;
|
|
189
|
+
const hasVoiceCol = (n) => voiceCols.some((c) => c.name === n);
|
|
190
|
+
if (!hasVoiceCol('disabled_reason')) {
|
|
191
|
+
await db.execute('ALTER TABLE voices ADD COLUMN disabled_reason TEXT');
|
|
192
|
+
}
|
|
193
|
+
return db;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* One-shot pre-existing-row backfill: any chat row with NULL slug gets
|
|
197
|
+
* one generated from its `work` text. Idempotent — second run finds no
|
|
198
|
+
* NULL rows and exits cheaply. Runs inside getDb() so it happens before
|
|
199
|
+
* any route handler can SELECT a chat with a missing slug.
|
|
200
|
+
*
|
|
201
|
+
* Uniqueness via inline existsFn closure to avoid a circular import on
|
|
202
|
+
* the chats module (which depends on getDb being done).
|
|
203
|
+
*/
|
|
204
|
+
async function backfillChatSlugs(db) {
|
|
205
|
+
const result = await db.execute('SELECT id, work, template_id FROM chats WHERE slug IS NULL ORDER BY created_at ASC');
|
|
206
|
+
if (result.rows.length === 0)
|
|
207
|
+
return;
|
|
208
|
+
const { generateChatSlug } = await import('../chat-slug.js');
|
|
209
|
+
for (const row of result.rows) {
|
|
210
|
+
const slug = await generateChatSlug({
|
|
211
|
+
work: row.work,
|
|
212
|
+
templateId: row.template_id,
|
|
213
|
+
existsFn: async (s) => {
|
|
214
|
+
const r = await db.execute({
|
|
215
|
+
sql: 'SELECT 1 FROM chats WHERE slug = ? LIMIT 1',
|
|
216
|
+
args: [s],
|
|
217
|
+
});
|
|
218
|
+
return r.rows.length > 0;
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
await db.execute({
|
|
222
|
+
sql: 'UPDATE chats SET slug = ? WHERE id = ?',
|
|
223
|
+
args: [slug, row.id],
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* @internal — for tests only. Closes the singleton handle and clears the
|
|
229
|
+
* cached instance so the next `getDb()` call re-initializes against the
|
|
230
|
+
* current `CHORUS_DB_PATH` env. Without this, vitest tests running in the
|
|
231
|
+
* same module instance would all share the first DB they opened.
|
|
232
|
+
*/
|
|
233
|
+
async function _resetDbForTests() {
|
|
234
|
+
if (dbInstance) {
|
|
235
|
+
try {
|
|
236
|
+
dbInstance.close();
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
/* best-effort */
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
dbInstance = null;
|
|
243
|
+
dbInitPromise = null;
|
|
244
|
+
}
|
|
245
|
+
function generateUlid() {
|
|
246
|
+
const now = Date.now();
|
|
247
|
+
const randomBytes = crypto.getRandomValues(new Uint8Array(10));
|
|
248
|
+
const timeBytes = now.toString(16).padStart(12, '0');
|
|
249
|
+
const randBytes = Array.from(randomBytes)
|
|
250
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
251
|
+
.join('');
|
|
252
|
+
return (timeBytes + randBytes).toUpperCase();
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../../src/lib/db/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DB seam — barrel re-exports per-table modules.
|
|
4
|
+
*
|
|
5
|
+
* Connection lifecycle (getDb, _resetDbForTests, resolveDbPath) lives in
|
|
6
|
+
* connection.ts; each table has its own file with schema + ops.
|
|
7
|
+
*
|
|
8
|
+
* Rollback lever for the libsql migration: the v0.7 swap from
|
|
9
|
+
* better-sqlite3 was a clean transport change. If a hot-path perf
|
|
10
|
+
* regression turns up in production, the rollback is a clean revert
|
|
11
|
+
* (NOT a swap to the sync `libsql` package — its API would require
|
|
12
|
+
* unwinding every `await` in this layer and its callers).
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.voices = exports.personas = exports.secrets = exports.settings = exports.templates = exports.phaseEvents = exports.chats = exports.resolveDbPath = exports.getDb = exports._resetDbForTests = void 0;
|
|
16
|
+
var connection_js_1 = require("./connection.js");
|
|
17
|
+
Object.defineProperty(exports, "_resetDbForTests", { enumerable: true, get: function () { return connection_js_1._resetDbForTests; } });
|
|
18
|
+
Object.defineProperty(exports, "getDb", { enumerable: true, get: function () { return connection_js_1.getDb; } });
|
|
19
|
+
Object.defineProperty(exports, "resolveDbPath", { enumerable: true, get: function () { return connection_js_1.resolveDbPath; } });
|
|
20
|
+
var chats_js_1 = require("./chats.js");
|
|
21
|
+
Object.defineProperty(exports, "chats", { enumerable: true, get: function () { return chats_js_1.chats; } });
|
|
22
|
+
var phase_events_js_1 = require("./phase-events.js");
|
|
23
|
+
Object.defineProperty(exports, "phaseEvents", { enumerable: true, get: function () { return phase_events_js_1.phaseEvents; } });
|
|
24
|
+
var templates_js_1 = require("./templates.js");
|
|
25
|
+
Object.defineProperty(exports, "templates", { enumerable: true, get: function () { return templates_js_1.templates; } });
|
|
26
|
+
var settings_js_1 = require("./settings.js");
|
|
27
|
+
Object.defineProperty(exports, "settings", { enumerable: true, get: function () { return settings_js_1.settings; } });
|
|
28
|
+
var secrets_js_1 = require("./secrets.js");
|
|
29
|
+
Object.defineProperty(exports, "secrets", { enumerable: true, get: function () { return secrets_js_1.secrets; } });
|
|
30
|
+
var personas_js_1 = require("./personas.js");
|
|
31
|
+
Object.defineProperty(exports, "personas", { enumerable: true, get: function () { return personas_js_1.personas; } });
|
|
32
|
+
var voices_js_1 = require("./voices.js");
|
|
33
|
+
Object.defineProperty(exports, "voices", { enumerable: true, get: function () { return voices_js_1.voices; } });
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/db/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAEH,iDAAyE;AAAhE,iHAAA,gBAAgB,OAAA;AAAE,sGAAA,KAAK,OAAA;AAAE,8GAAA,aAAa,OAAA;AAC/C,uCAAmC;AAA1B,iGAAA,KAAK,OAAA;AACd,qDAAgD;AAAvC,8GAAA,WAAW,OAAA;AACpB,+CAA2C;AAAlC,yGAAA,SAAS,OAAA;AAClB,6CAAyC;AAAhC,uGAAA,QAAQ,OAAA;AACjB,2CAAuC;AAA9B,qGAAA,OAAO,OAAA;AAChB,6CAA0D;AAAjD,uGAAA,QAAQ,OAAA;AACjB,yCAA4D;AAAnD,mGAAA,MAAM,OAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.personas = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const connection_js_1 = require("./connection.js");
|
|
6
|
+
const PersonaRowSchema = zod_1.z.object({
|
|
7
|
+
id: zod_1.z.string(),
|
|
8
|
+
label: zod_1.z.string(),
|
|
9
|
+
one_liner: zod_1.z.string(),
|
|
10
|
+
system_prompt: zod_1.z.string(),
|
|
11
|
+
recommended_lineage: zod_1.z.string().nullable(),
|
|
12
|
+
builtin: zod_1.z.coerce.boolean(),
|
|
13
|
+
forked_from: zod_1.z.string().nullable(),
|
|
14
|
+
created_at: zod_1.z.number().int(),
|
|
15
|
+
updated_at: zod_1.z.number().int(),
|
|
16
|
+
});
|
|
17
|
+
exports.personas = {
|
|
18
|
+
async upsert(input) {
|
|
19
|
+
const db = await (0, connection_js_1.getDb)();
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const existing = await exports.personas.getById(input.id);
|
|
22
|
+
await db.execute({
|
|
23
|
+
sql: `
|
|
24
|
+
INSERT OR REPLACE INTO personas
|
|
25
|
+
(id, label, one_liner, system_prompt, recommended_lineage, builtin, forked_from, created_at, updated_at)
|
|
26
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
27
|
+
`,
|
|
28
|
+
args: [
|
|
29
|
+
input.id,
|
|
30
|
+
input.label,
|
|
31
|
+
input.one_liner,
|
|
32
|
+
input.system_prompt,
|
|
33
|
+
input.recommended_lineage ?? null,
|
|
34
|
+
input.builtin ? 1 : 0,
|
|
35
|
+
input.forked_from ?? null,
|
|
36
|
+
existing?.created_at ?? now,
|
|
37
|
+
now,
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
const row = await exports.personas.getById(input.id);
|
|
41
|
+
if (!row)
|
|
42
|
+
throw new Error(`personas.upsert: row vanished: ${input.id}`);
|
|
43
|
+
return row;
|
|
44
|
+
},
|
|
45
|
+
async list() {
|
|
46
|
+
const db = await (0, connection_js_1.getDb)();
|
|
47
|
+
const result = await db.execute('SELECT * FROM personas ORDER BY label ASC');
|
|
48
|
+
return result.rows.map((row) => PersonaRowSchema.parse(row));
|
|
49
|
+
},
|
|
50
|
+
async getById(id) {
|
|
51
|
+
const db = await (0, connection_js_1.getDb)();
|
|
52
|
+
const result = await db.execute({
|
|
53
|
+
sql: 'SELECT * FROM personas WHERE id = ?',
|
|
54
|
+
args: [id],
|
|
55
|
+
});
|
|
56
|
+
if (result.rows.length === 0)
|
|
57
|
+
return null;
|
|
58
|
+
return PersonaRowSchema.parse(result.rows[0]);
|
|
59
|
+
},
|
|
60
|
+
async delete(id) {
|
|
61
|
+
const db = await (0, connection_js_1.getDb)();
|
|
62
|
+
await db.execute({ sql: 'DELETE FROM personas WHERE id = ?', args: [id] });
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
//# sourceMappingURL=personas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personas.js","sourceRoot":"","sources":["../../../src/lib/db/personas.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,mDAAwC;AAExC,MAAM,gBAAgB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChC,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE;IACrB,aAAa,EAAE,OAAC,CAAC,MAAM,EAAE;IACzB,mBAAmB,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,OAAO,EAAE,OAAC,CAAC,MAAM,CAAC,OAAO,EAAE;IAC3B,WAAW,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC5B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;CAC7B,CAAC,CAAC;AAcU,QAAA,QAAQ,GAAG;IACtB,KAAK,CAAC,MAAM,CAAC,KAAyB;QACpC,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,gBAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAElD,MAAM,EAAE,CAAC,OAAO,CAAC;YACf,GAAG,EAAE;;;;OAIJ;YACD,IAAI,EAAE;gBACJ,KAAK,CAAC,EAAE;gBACR,KAAK,CAAC,KAAK;gBACX,KAAK,CAAC,SAAS;gBACf,KAAK,CAAC,aAAa;gBACnB,KAAK,CAAC,mBAAmB,IAAI,IAAI;gBACjC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrB,KAAK,CAAC,WAAW,IAAI,IAAI;gBACzB,QAAQ,EAAE,UAAU,IAAI,GAAG;gBAC3B,GAAG;aACJ;SACF,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,MAAM,gBAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACxE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,2CAA2C,CAAC,CAAC;QAC7E,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;YAC9B,GAAG,EAAE,qCAAqC;YAC1C,IAAI,EAAE,CAAC,EAAE,CAAC;SACX,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,mCAAmC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.phaseEvents = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const connection_js_1 = require("./connection.js");
|
|
6
|
+
const PhaseEventSchema = zod_1.z.object({
|
|
7
|
+
id: zod_1.z.number().int(),
|
|
8
|
+
chat_id: zod_1.z.string(),
|
|
9
|
+
phase_idx: zod_1.z.number().int(),
|
|
10
|
+
phase_kind: zod_1.z.enum([
|
|
11
|
+
'plan',
|
|
12
|
+
'spec',
|
|
13
|
+
'tests',
|
|
14
|
+
'implement',
|
|
15
|
+
'review',
|
|
16
|
+
'verify',
|
|
17
|
+
'divergence',
|
|
18
|
+
'review_only',
|
|
19
|
+
]),
|
|
20
|
+
role: zod_1.z.enum(['doer', 'reviewer']),
|
|
21
|
+
agent_id: zod_1.z.string().nullable(),
|
|
22
|
+
// 'warning' is the persisted state for cli_warning events that aren't
|
|
23
|
+
// terminal failures — model_fallback transitions in particular. Pre-fix
|
|
24
|
+
// every cli_warning was stored as 'errored', which made a successful
|
|
25
|
+
// per-slot fallback look like a reviewer crash in audit logs. Replay
|
|
26
|
+
// (phaseEventToRunnerEvent) ignores this state the same way it ignores
|
|
27
|
+
// 'errored' / 'reviewing' / 'approved' / 'revising', so live SSE
|
|
28
|
+
// traffic is unaffected.
|
|
29
|
+
state: zod_1.z.enum([
|
|
30
|
+
'drafting',
|
|
31
|
+
'submitted',
|
|
32
|
+
'reviewing',
|
|
33
|
+
'approved',
|
|
34
|
+
'revising',
|
|
35
|
+
'blocked',
|
|
36
|
+
'errored',
|
|
37
|
+
'warning',
|
|
38
|
+
]),
|
|
39
|
+
output: zod_1.z.string().nullable(),
|
|
40
|
+
cost_usd: zod_1.z.number().default(0),
|
|
41
|
+
tokens_in: zod_1.z.number().int().default(0),
|
|
42
|
+
tokens_out: zod_1.z.number().int().default(0),
|
|
43
|
+
started_at: zod_1.z.number().int(),
|
|
44
|
+
finished_at: zod_1.z.number().int().nullable(),
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Hard cap on phase_events.output length. SQLite handles big TEXT cells
|
|
48
|
+
* fine in isolation, but libsql wraps each row's columns in a result
|
|
49
|
+
* payload that gets reshipped on every read. A 4 MB reviewer transcript
|
|
50
|
+
* stored inline turns every `phaseEvents.list(chatId)` call into a 4 MB
|
|
51
|
+
* fetch — and the run page calls list() on every SSE re-attach. Cap at
|
|
52
|
+
* 256 KB; if a real output is bigger we keep the head + tail and emit a
|
|
53
|
+
* truncation marker pointing at the on-disk artifact dir. Long-form
|
|
54
|
+
* artifacts already live under ~/.chorus/chats/<id>/.
|
|
55
|
+
*/
|
|
56
|
+
const MAX_PHASE_OUTPUT_BYTES = 256 * 1024;
|
|
57
|
+
function buildTruncationMarker(chatId) {
|
|
58
|
+
return `\n\n... [truncated — see ~/.chorus/chats/${chatId}/ for full transcript] ...\n\n`;
|
|
59
|
+
}
|
|
60
|
+
function capOutput(output, chatId) {
|
|
61
|
+
if (output === null)
|
|
62
|
+
return null;
|
|
63
|
+
// Byte length, not char count — SQLite stores UTF-8 and a 4 MB string
|
|
64
|
+
// of multi-byte chars would still bloat the row.
|
|
65
|
+
const byteLen = Buffer.byteLength(output, 'utf-8');
|
|
66
|
+
if (byteLen <= MAX_PHASE_OUTPUT_BYTES)
|
|
67
|
+
return output;
|
|
68
|
+
// Keep head (192 KB) + tail (32 KB). Bytes-based slicing on the
|
|
69
|
+
// underlying Buffer to stay under the cap even with multi-byte runes.
|
|
70
|
+
const buf = Buffer.from(output, 'utf-8');
|
|
71
|
+
const headBytes = 192 * 1024;
|
|
72
|
+
const tailBytes = 32 * 1024;
|
|
73
|
+
const head = buf.subarray(0, headBytes).toString('utf-8');
|
|
74
|
+
const tail = buf.subarray(buf.length - tailBytes).toString('utf-8');
|
|
75
|
+
return head + buildTruncationMarker(chatId) + tail;
|
|
76
|
+
}
|
|
77
|
+
exports.phaseEvents = {
|
|
78
|
+
async create(event) {
|
|
79
|
+
const db = await (0, connection_js_1.getDb)();
|
|
80
|
+
const validated = PhaseEventSchema.omit({ id: true }).parse(event);
|
|
81
|
+
const output = capOutput(validated.output, validated.chat_id);
|
|
82
|
+
const result = await db.execute({
|
|
83
|
+
sql: `
|
|
84
|
+
INSERT INTO phase_events (chat_id, phase_idx, phase_kind, role, agent_id, state, output, cost_usd, tokens_in, tokens_out, started_at, finished_at)
|
|
85
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
86
|
+
`,
|
|
87
|
+
args: [
|
|
88
|
+
validated.chat_id,
|
|
89
|
+
validated.phase_idx,
|
|
90
|
+
validated.phase_kind,
|
|
91
|
+
validated.role,
|
|
92
|
+
validated.agent_id,
|
|
93
|
+
validated.state,
|
|
94
|
+
output,
|
|
95
|
+
validated.cost_usd,
|
|
96
|
+
validated.tokens_in,
|
|
97
|
+
validated.tokens_out,
|
|
98
|
+
validated.started_at,
|
|
99
|
+
validated.finished_at,
|
|
100
|
+
],
|
|
101
|
+
});
|
|
102
|
+
// libsql returns lastInsertRowid as bigint; cast to number for the
|
|
103
|
+
// existing API. Chorus row counts stay well under 2^53.
|
|
104
|
+
const id = Number(result.lastInsertRowid);
|
|
105
|
+
const row = await exports.phaseEvents.getById(id);
|
|
106
|
+
if (!row)
|
|
107
|
+
throw new Error(`phaseEvents.create: row vanished: ${id}`);
|
|
108
|
+
return row;
|
|
109
|
+
},
|
|
110
|
+
async list(chatId) {
|
|
111
|
+
const db = await (0, connection_js_1.getDb)();
|
|
112
|
+
const result = await db.execute({
|
|
113
|
+
sql: 'SELECT * FROM phase_events WHERE chat_id = ? ORDER BY phase_idx, id',
|
|
114
|
+
args: [chatId],
|
|
115
|
+
});
|
|
116
|
+
return result.rows.map((row) => PhaseEventSchema.parse(row));
|
|
117
|
+
},
|
|
118
|
+
async getById(id) {
|
|
119
|
+
const db = await (0, connection_js_1.getDb)();
|
|
120
|
+
const result = await db.execute({
|
|
121
|
+
sql: 'SELECT * FROM phase_events WHERE id = ?',
|
|
122
|
+
args: [id],
|
|
123
|
+
});
|
|
124
|
+
if (result.rows.length === 0)
|
|
125
|
+
return null;
|
|
126
|
+
return PhaseEventSchema.parse(result.rows[0]);
|
|
127
|
+
},
|
|
128
|
+
async update(id, partial) {
|
|
129
|
+
const db = await (0, connection_js_1.getDb)();
|
|
130
|
+
const event = await exports.phaseEvents.getById(id);
|
|
131
|
+
if (!event) {
|
|
132
|
+
throw new Error(`Phase event ${id} not found`);
|
|
133
|
+
}
|
|
134
|
+
// CRITICAL: distinguish "output omitted from partial" (preserve
|
|
135
|
+
// existing) from "output explicitly null" (caller wants to clear).
|
|
136
|
+
// The naive `partial.output ?? event.output` collapses both into
|
|
137
|
+
// "preserve" because null ?? x → x, which would silently drop
|
|
138
|
+
// intentional clears. Detect via the `in` operator on the typed key.
|
|
139
|
+
// Already-capped outputs in event.output pass through unchanged
|
|
140
|
+
// (cap is idempotent); only newly-supplied outputs need re-capping.
|
|
141
|
+
const nextOutput = 'output' in partial
|
|
142
|
+
? capOutput(partial.output ?? null, event.chat_id)
|
|
143
|
+
: event.output;
|
|
144
|
+
const updated = { ...event, ...partial, output: nextOutput };
|
|
145
|
+
await db.execute({
|
|
146
|
+
sql: `
|
|
147
|
+
UPDATE phase_events
|
|
148
|
+
SET chat_id = ?, phase_idx = ?, phase_kind = ?, role = ?, agent_id = ?, state = ?, output = ?, cost_usd = ?, tokens_in = ?, tokens_out = ?, finished_at = ?
|
|
149
|
+
WHERE id = ?
|
|
150
|
+
`,
|
|
151
|
+
args: [
|
|
152
|
+
updated.chat_id,
|
|
153
|
+
updated.phase_idx,
|
|
154
|
+
updated.phase_kind,
|
|
155
|
+
updated.role,
|
|
156
|
+
updated.agent_id,
|
|
157
|
+
updated.state,
|
|
158
|
+
updated.output,
|
|
159
|
+
updated.cost_usd,
|
|
160
|
+
updated.tokens_in,
|
|
161
|
+
updated.tokens_out,
|
|
162
|
+
updated.finished_at,
|
|
163
|
+
id,
|
|
164
|
+
],
|
|
165
|
+
});
|
|
166
|
+
const row = await exports.phaseEvents.getById(id);
|
|
167
|
+
if (!row)
|
|
168
|
+
throw new Error(`phaseEvents.update: row vanished: ${id}`);
|
|
169
|
+
return row;
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
//# sourceMappingURL=phase-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"phase-events.js","sourceRoot":"","sources":["../../../src/lib/db/phase-events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.secrets = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const connection_js_1 = require("./connection.js");
|
|
6
|
+
const SecretSchema = zod_1.z.object({
|
|
7
|
+
provider: zod_1.z.string(),
|
|
8
|
+
kind: zod_1.z.enum(['api_key', 'cli_subscription']),
|
|
9
|
+
value: zod_1.z.string(),
|
|
10
|
+
meta: zod_1.z.string().nullable(),
|
|
11
|
+
updated_at: zod_1.z.number().int(),
|
|
12
|
+
});
|
|
13
|
+
exports.secrets = {
|
|
14
|
+
async set(provider, kind, value, meta) {
|
|
15
|
+
const db = await (0, connection_js_1.getDb)();
|
|
16
|
+
await db.execute({
|
|
17
|
+
sql: 'INSERT OR REPLACE INTO secrets (provider, kind, value, meta, updated_at) VALUES (?, ?, ?, ?, ?)',
|
|
18
|
+
args: [provider, kind, value, meta ? JSON.stringify(meta) : null, Date.now()],
|
|
19
|
+
});
|
|
20
|
+
},
|
|
21
|
+
async get(provider) {
|
|
22
|
+
const db = await (0, connection_js_1.getDb)();
|
|
23
|
+
const result = await db.execute({
|
|
24
|
+
sql: 'SELECT * FROM secrets WHERE provider = ?',
|
|
25
|
+
args: [provider],
|
|
26
|
+
});
|
|
27
|
+
if (result.rows.length === 0)
|
|
28
|
+
return null;
|
|
29
|
+
return SecretSchema.parse(result.rows[0]);
|
|
30
|
+
},
|
|
31
|
+
async list() {
|
|
32
|
+
const db = await (0, connection_js_1.getDb)();
|
|
33
|
+
const result = await db.execute('SELECT provider, kind, meta, updated_at FROM secrets');
|
|
34
|
+
return result.rows.map((row) => SecretSchema.omit({ value: true })
|
|
35
|
+
.extend({ meta: zod_1.z.string().nullable() })
|
|
36
|
+
.parse(row));
|
|
37
|
+
},
|
|
38
|
+
/**
|
|
39
|
+
* Idempotent delete — returns true if a row was actually removed,
|
|
40
|
+
* false if the secret didn't exist. Callers can use the boolean to
|
|
41
|
+
* disambiguate "rotated" from "no-op", but the wire surface
|
|
42
|
+
* (DELETE /secrets/:provider) treats both as success per REST norms.
|
|
43
|
+
*/
|
|
44
|
+
async delete(provider) {
|
|
45
|
+
const db = await (0, connection_js_1.getDb)();
|
|
46
|
+
const result = await db.execute({
|
|
47
|
+
sql: 'DELETE FROM secrets WHERE provider = ?',
|
|
48
|
+
args: [provider],
|
|
49
|
+
});
|
|
50
|
+
return Number(result.rowsAffected ?? 0) > 0;
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=secrets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secrets.js","sourceRoot":"","sources":["../../../src/lib/db/secrets.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AACxB,mDAAwC;AAExC,MAAM,YAAY,GAAG,OAAC,CAAC,MAAM,CAAC;IAC5B,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;IACpB,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAC7C,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,UAAU,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;CAC7B,CAAC,CAAC;AAIU,QAAA,OAAO,GAAG;IACrB,KAAK,CAAC,GAAG,CACP,QAAgB,EAChB,IAAoC,EACpC,KAAa,EACb,IAA8B;QAE9B,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,EAAE,CAAC,OAAO,CAAC;YACf,GAAG,EAAE,iGAAiG;YACtG,IAAI,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;SAC9E,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,QAAgB;QACxB,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;YAC9B,GAAG,EAAE,0CAA0C;YAC/C,IAAI,EAAE,CAAC,QAAQ,CAAC;SACjB,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,OAAO,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAC7B,sDAAsD,CACvD,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAC7B,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;aAC/B,MAAM,CAAC,EAAE,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;aACvC,KAAK,CAAC,GAAG,CAAC,CACd,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,MAAM,EAAE,GAAG,MAAM,IAAA,qBAAK,GAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC;YAC9B,GAAG,EAAE,wCAAwC;YAC7C,IAAI,EAAE,CAAC,QAAQ,CAAC;SACjB,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.settings = void 0;
|
|
4
|
+
const connection_js_1 = require("./connection.js");
|
|
5
|
+
exports.settings = {
|
|
6
|
+
async get(key) {
|
|
7
|
+
const db = await (0, connection_js_1.getDb)();
|
|
8
|
+
const result = await db.execute({
|
|
9
|
+
sql: 'SELECT value FROM settings WHERE key = ?',
|
|
10
|
+
args: [key],
|
|
11
|
+
});
|
|
12
|
+
if (result.rows.length === 0)
|
|
13
|
+
return null;
|
|
14
|
+
const value = result.rows[0].value;
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(value);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
async set(key, value) {
|
|
23
|
+
const db = await (0, connection_js_1.getDb)();
|
|
24
|
+
const stringValue = typeof value === 'string' ? value : JSON.stringify(value);
|
|
25
|
+
await db.execute({
|
|
26
|
+
sql: 'INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)',
|
|
27
|
+
args: [key, stringValue],
|
|
28
|
+
});
|
|
29
|
+
},
|
|
30
|
+
async getAll() {
|
|
31
|
+
const db = await (0, connection_js_1.getDb)();
|
|
32
|
+
const result = await db.execute('SELECT key, value FROM settings');
|
|
33
|
+
const out = {};
|
|
34
|
+
for (const row of result.rows) {
|
|
35
|
+
const k = row.key;
|
|
36
|
+
const v = row.value;
|
|
37
|
+
try {
|
|
38
|
+
out[k] = JSON.parse(v);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
out[k] = v;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
//# sourceMappingURL=settings.js.map
|