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,290 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports._testing = void 0;
|
|
37
|
+
exports.isTelemetryEnabled = isTelemetryEnabled;
|
|
38
|
+
exports.getTelemetryStatus = getTelemetryStatus;
|
|
39
|
+
exports.setTelemetryEnabled = setTelemetryEnabled;
|
|
40
|
+
exports.getOrCreateInstallId = getOrCreateInstallId;
|
|
41
|
+
exports.countChatsLast24h = countChatsLast24h;
|
|
42
|
+
exports.buildPayload = buildPayload;
|
|
43
|
+
exports.sendHeartbeat = sendHeartbeat;
|
|
44
|
+
exports.startTelemetryHeartbeat = startTelemetryHeartbeat;
|
|
45
|
+
/**
|
|
46
|
+
* Opt-out telemetry heartbeat (round-2-deferred §4).
|
|
47
|
+
*
|
|
48
|
+
* Daemon-side ping to chorus.codes once per boot + once per 24h. The
|
|
49
|
+
* payload is a fixed, audited shape — version, OS, arch, node major,
|
|
50
|
+
* daemon uptime, count of chats in the last 24h. No chat content, no
|
|
51
|
+
* file paths, no hostnames, no API keys.
|
|
52
|
+
*
|
|
53
|
+
* Three opt-out paths, any one disables:
|
|
54
|
+
* 1. CHORUS_TELEMETRY=0 environment variable
|
|
55
|
+
* 2. ~/.chorus/no-telemetry touch-file (matches cargo / brew convention)
|
|
56
|
+
* 3. settings key `telemetry.enabled` set to false
|
|
57
|
+
*
|
|
58
|
+
* The endpoint may not exist yet — sends are fire-and-forget with a 5s
|
|
59
|
+
* timeout; failure logs at debug level only and never blocks the daemon
|
|
60
|
+
* or surfaces to the user. Schema-versioned (`schema: 1`) so future
|
|
61
|
+
* payload changes are additive and old daemons keep working.
|
|
62
|
+
*/
|
|
63
|
+
const fs = __importStar(require("fs"));
|
|
64
|
+
const os = __importStar(require("os"));
|
|
65
|
+
const path = __importStar(require("path"));
|
|
66
|
+
const crypto_1 = require("crypto");
|
|
67
|
+
const index_js_1 = require("./db/index.js");
|
|
68
|
+
const ENDPOINT = 'https://chorus.codes/api/telemetry';
|
|
69
|
+
const SETTINGS_KEY = 'telemetry.enabled';
|
|
70
|
+
const HEARTBEAT_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
71
|
+
const SEND_TIMEOUT_MS = 5_000;
|
|
72
|
+
function chorusDir() {
|
|
73
|
+
return path.join(os.homedir(), '.chorus');
|
|
74
|
+
}
|
|
75
|
+
function installIdPath() {
|
|
76
|
+
return path.join(chorusDir(), 'install-id');
|
|
77
|
+
}
|
|
78
|
+
function noTelemetryPath() {
|
|
79
|
+
return path.join(chorusDir(), 'no-telemetry');
|
|
80
|
+
}
|
|
81
|
+
/** Common falsy strings users naturally type to mean "off". */
|
|
82
|
+
const ENV_DISABLE_VALUES = new Set(['0', 'false', 'no', 'off']);
|
|
83
|
+
/**
|
|
84
|
+
* Check all three opt-out paths. Returns false if any one disables.
|
|
85
|
+
* Settings DB is consulted last so env / touch-file work even when the
|
|
86
|
+
* DB hasn't been opened yet (e.g. first-boot probe).
|
|
87
|
+
*
|
|
88
|
+
* `CHORUS_TELEMETRY` accepts any of `0`/`false`/`no`/`off` (case
|
|
89
|
+
* insensitive); anything else leaves telemetry enabled. The variable
|
|
90
|
+
* is a soft kill switch, not a strict on/off enum.
|
|
91
|
+
*/
|
|
92
|
+
async function isTelemetryEnabled() {
|
|
93
|
+
const env = process.env.CHORUS_TELEMETRY;
|
|
94
|
+
if (env !== undefined && ENV_DISABLE_VALUES.has(env.toLowerCase()))
|
|
95
|
+
return false;
|
|
96
|
+
if (fs.existsSync(noTelemetryPath()))
|
|
97
|
+
return false;
|
|
98
|
+
try {
|
|
99
|
+
const raw = await index_js_1.settings.get(SETTINGS_KEY);
|
|
100
|
+
if (raw === false)
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// DB not ready — assume enabled at the per-call level. The boot
|
|
105
|
+
// wiring won't hit this path because it runs after seedSettings().
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Detailed status used by the cockpit UI: same effective answer as
|
|
111
|
+
* `isTelemetryEnabled` plus a breakdown of which path is winning, so the
|
|
112
|
+
* settings page can explain "disabled by env var" rather than show a toggle
|
|
113
|
+
* that secretly does nothing.
|
|
114
|
+
*/
|
|
115
|
+
async function getTelemetryStatus() {
|
|
116
|
+
const env = process.env.CHORUS_TELEMETRY;
|
|
117
|
+
const envOverride = env !== undefined && ENV_DISABLE_VALUES.has(env.toLowerCase());
|
|
118
|
+
const fileOverride = fs.existsSync(noTelemetryPath());
|
|
119
|
+
let settingValue;
|
|
120
|
+
try {
|
|
121
|
+
const raw = await index_js_1.settings.get(SETTINGS_KEY);
|
|
122
|
+
if (raw === true || raw === false)
|
|
123
|
+
settingValue = raw;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
/* DB not ready — leave undefined */
|
|
127
|
+
}
|
|
128
|
+
const enabled = !envOverride && !fileOverride && settingValue !== false;
|
|
129
|
+
return { enabled, envOverride, fileOverride, settingValue, endpoint: ENDPOINT };
|
|
130
|
+
}
|
|
131
|
+
/** Set the persisted opt-in flag. Env / file overrides still trump it. */
|
|
132
|
+
async function setTelemetryEnabled(value) {
|
|
133
|
+
await index_js_1.settings.set(SETTINGS_KEY, value);
|
|
134
|
+
return getTelemetryStatus();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Read or mint an anonymous install ID. Lives in `~/.chorus/install-id`
|
|
138
|
+
* as a single line; user can `rm` it to reset (a new UUID is minted on
|
|
139
|
+
* the next call). Not derived from anything machine-specific.
|
|
140
|
+
*/
|
|
141
|
+
function getOrCreateInstallId() {
|
|
142
|
+
const dir = chorusDir();
|
|
143
|
+
if (!fs.existsSync(dir))
|
|
144
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
145
|
+
const file = installIdPath();
|
|
146
|
+
if (fs.existsSync(file)) {
|
|
147
|
+
const existing = fs.readFileSync(file, 'utf-8').trim();
|
|
148
|
+
// Tolerate manual edits / partial writes — only accept UUID-shaped
|
|
149
|
+
// strings (any version); anything else gets replaced with a fresh ID
|
|
150
|
+
// rather than failing the heartbeat. randomUUID() emits v4, but the
|
|
151
|
+
// shape check is intentionally version-agnostic so a hand-edited v7
|
|
152
|
+
// installId from a downstream tool keeps working.
|
|
153
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(existing)) {
|
|
154
|
+
return existing;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const fresh = (0, crypto_1.randomUUID)();
|
|
158
|
+
// 0o600 — readable + writable only by the daemon's user. Belt-and-
|
|
159
|
+
// braces against ID correlation across users on a shared host.
|
|
160
|
+
fs.writeFileSync(file, fresh + '\n', { mode: 0o600 });
|
|
161
|
+
return fresh;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Count chats created in the last 24 hours. Pure DB read; no chat
|
|
165
|
+
* content, just a count of rows.
|
|
166
|
+
*/
|
|
167
|
+
async function countChatsLast24h(now = Date.now()) {
|
|
168
|
+
const cutoff = now - HEARTBEAT_INTERVAL_MS;
|
|
169
|
+
const db = await (0, index_js_1.getDb)();
|
|
170
|
+
const result = await db.execute({
|
|
171
|
+
sql: 'SELECT COUNT(*) AS n FROM chats WHERE created_at >= ?',
|
|
172
|
+
args: [cutoff],
|
|
173
|
+
});
|
|
174
|
+
const row = result.rows[0];
|
|
175
|
+
if (!row)
|
|
176
|
+
return 0;
|
|
177
|
+
// libsql returns column values via row.n (object access) when columns
|
|
178
|
+
// are aliased — index access is also valid. Be defensive across both.
|
|
179
|
+
const raw = row.n ?? row[0];
|
|
180
|
+
const n = typeof raw === 'bigint' ? Number(raw) : Number(raw ?? 0);
|
|
181
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : 0;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Assemble the payload. Pure shape — easy to test against the spec.
|
|
185
|
+
* `version` is read from package.json so a stale literal can't drift;
|
|
186
|
+
* caller supplies it (the daemon already imports its own version).
|
|
187
|
+
*/
|
|
188
|
+
async function buildPayload(args) {
|
|
189
|
+
const now = args.now ?? Date.now();
|
|
190
|
+
// Node 'major' only — minor/patch leak less-useful detail and bloat
|
|
191
|
+
// the analytics cardinality.
|
|
192
|
+
const nodeMajor = process.versions.node.split('.')[0];
|
|
193
|
+
return {
|
|
194
|
+
schema: 1,
|
|
195
|
+
installId: getOrCreateInstallId(),
|
|
196
|
+
version: args.version,
|
|
197
|
+
os: process.platform,
|
|
198
|
+
arch: process.arch,
|
|
199
|
+
node: nodeMajor,
|
|
200
|
+
daemonUptimeSeconds: Math.max(0, Math.floor((now - args.daemonStartedAt) / 1000)),
|
|
201
|
+
chatsLast24h: await countChatsLast24h(now),
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Fire-and-forget POST. Honours all three opt-out paths. Never throws —
|
|
206
|
+
* a dead endpoint, DB error during `buildPayload`, fs error during
|
|
207
|
+
* `getOrCreateInstallId`, or any other failure resolves to `null`
|
|
208
|
+
* rather than rejecting. Returns the sent payload on success so tests
|
|
209
|
+
* can assert exact bytes without scraping log lines.
|
|
210
|
+
*
|
|
211
|
+
* Round-1 dogfood (PR #6) caught a bug here: `buildPayload` ran
|
|
212
|
+
* outside the try/catch, so a transient libsql disconnect during
|
|
213
|
+
* shutdown rejected the promise the daemon discarded with `void`,
|
|
214
|
+
* producing an unhandled rejection. The whole body is now wrapped.
|
|
215
|
+
*/
|
|
216
|
+
async function sendHeartbeat(args) {
|
|
217
|
+
const log = args.log ?? ((m) => console.log(`[telemetry] ${m}`));
|
|
218
|
+
try {
|
|
219
|
+
if (!(await isTelemetryEnabled()))
|
|
220
|
+
return null;
|
|
221
|
+
const payload = await buildPayload({
|
|
222
|
+
version: args.version,
|
|
223
|
+
daemonStartedAt: args.daemonStartedAt,
|
|
224
|
+
});
|
|
225
|
+
const fetchFn = args.fetchImpl ?? fetch;
|
|
226
|
+
const controller = new AbortController();
|
|
227
|
+
const timeout = setTimeout(() => controller.abort(), SEND_TIMEOUT_MS);
|
|
228
|
+
try {
|
|
229
|
+
await fetchFn(ENDPOINT, {
|
|
230
|
+
method: 'POST',
|
|
231
|
+
headers: { 'Content-Type': 'application/json' },
|
|
232
|
+
body: JSON.stringify(payload),
|
|
233
|
+
signal: controller.signal,
|
|
234
|
+
});
|
|
235
|
+
return payload;
|
|
236
|
+
}
|
|
237
|
+
finally {
|
|
238
|
+
clearTimeout(timeout);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
log(`heartbeat failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Boot wiring — fires once now (after a small delay so the daemon is
|
|
248
|
+
* definitely listening) and then every 24h. Returns the interval handle
|
|
249
|
+
* so the daemon can clear it on shutdown.
|
|
250
|
+
*/
|
|
251
|
+
function startTelemetryHeartbeat(args) {
|
|
252
|
+
const setIntervalFn = args.setIntervalImpl ?? setInterval;
|
|
253
|
+
const setTimeoutFn = args.setTimeoutImpl ?? setTimeout;
|
|
254
|
+
// Small delay on first send so the daemon is definitely up + the DB is
|
|
255
|
+
// open. 5s is enough; the heartbeat itself has a 5s timeout.
|
|
256
|
+
const bootHandle = setTimeoutFn(() => {
|
|
257
|
+
void sendHeartbeat({ version: args.version, daemonStartedAt: args.daemonStartedAt });
|
|
258
|
+
}, 5_000);
|
|
259
|
+
const intervalHandle = setIntervalFn(() => {
|
|
260
|
+
void sendHeartbeat({ version: args.version, daemonStartedAt: args.daemonStartedAt });
|
|
261
|
+
}, HEARTBEAT_INTERVAL_MS);
|
|
262
|
+
// Don't pin the event loop. If the daemon ever wants natural exit
|
|
263
|
+
// (e.g. SIGTERM → fastify.close → drain pendings), telemetry timers
|
|
264
|
+
// shouldn't keep it alive. The daemon also calls .stop() on signal,
|
|
265
|
+
// so this is belt-and-braces.
|
|
266
|
+
if (typeof bootHandle.unref === 'function') {
|
|
267
|
+
bootHandle.unref();
|
|
268
|
+
}
|
|
269
|
+
if (typeof intervalHandle.unref === 'function') {
|
|
270
|
+
intervalHandle.unref();
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
stop: () => {
|
|
274
|
+
clearTimeout(bootHandle);
|
|
275
|
+
clearInterval(intervalHandle);
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
// Test-only seams. These are exported under a stable namespace so the
|
|
280
|
+
// test file can mutate paths without touching `~/.chorus` on the host.
|
|
281
|
+
exports._testing = {
|
|
282
|
+
installIdPath,
|
|
283
|
+
noTelemetryPath,
|
|
284
|
+
chorusDir,
|
|
285
|
+
ENDPOINT,
|
|
286
|
+
SETTINGS_KEY,
|
|
287
|
+
HEARTBEAT_INTERVAL_MS,
|
|
288
|
+
SEND_TIMEOUT_MS,
|
|
289
|
+
};
|
|
290
|
+
//# sourceMappingURL=telemetry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/lib/telemetry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TemplateSchema = exports.PhaseSchema = exports.DEFAULT_TMUX_PHASE_TIMEOUT_MS = exports.DEFAULT_PHASE_TIMEOUT_MS = void 0;
|
|
4
|
+
exports.isReviewOnlyPhase = isReviewOnlyPhase;
|
|
5
|
+
exports.templateRequiresArtifact = templateRequiresArtifact;
|
|
6
|
+
const zod_1 = require("zod");
|
|
7
|
+
/**
|
|
8
|
+
* Single phase within a template.
|
|
9
|
+
*
|
|
10
|
+
* Two phase shapes share the schema:
|
|
11
|
+
*
|
|
12
|
+
* - Standard phases (kind: plan | spec | tests | implement | review |
|
|
13
|
+
* verify | divergence): doer required, optional reviewer, iterate
|
|
14
|
+
* loop with rounds. The runner spawns the doer, then any reviewers,
|
|
15
|
+
* then loops on disagreement up to maxRounds.
|
|
16
|
+
*
|
|
17
|
+
* - Review-only phase (kind: review_only): NO doer block. The artifact
|
|
18
|
+
* is supplied at chat-create time and written into the doer answer
|
|
19
|
+
* slot synthetically. iterate is ignored — review-only is always one
|
|
20
|
+
* pass. ship is also auto-skipped (no doer diff to commit).
|
|
21
|
+
*
|
|
22
|
+
* The two are unified into one PhaseSchema via a discriminated union on
|
|
23
|
+
* `kind`. Templates pick exactly one shape per phase and the runner
|
|
24
|
+
* branches on the discriminator.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Default per-phase wait budget for the headless transport, used when a
|
|
28
|
+
* template doesn't override `timeoutMs`. Headless wraps a streaming
|
|
29
|
+
* subprocess; 10 min is the spawn-level wall.
|
|
30
|
+
*/
|
|
31
|
+
exports.DEFAULT_PHASE_TIMEOUT_MS = 10 * 60 * 1000;
|
|
32
|
+
/**
|
|
33
|
+
* Default per-phase wait budget for the tmux file-watch path. Tighter
|
|
34
|
+
* than headless because the tmux flow polls a file the CLI is writing
|
|
35
|
+
* via a TUI — if 5 min pass with no answer.md content the CLI is almost
|
|
36
|
+
* certainly stuck on a prompt or has crashed silently. A template's
|
|
37
|
+
* `phase.timeoutMs` override beats this default on either transport.
|
|
38
|
+
*/
|
|
39
|
+
exports.DEFAULT_TMUX_PHASE_TIMEOUT_MS = 5 * 60 * 1000;
|
|
40
|
+
/**
|
|
41
|
+
* Bounds on the optional per-phase timeout override.
|
|
42
|
+
* 30s floor catches typos; 1h ceiling catches misconfigs that would let a
|
|
43
|
+
* runaway CLI sit forever. A template that legitimately needs longer can
|
|
44
|
+
* be raised here, but anything beyond an hour is almost certainly a bug.
|
|
45
|
+
*/
|
|
46
|
+
const PHASE_TIMEOUT_MIN_MS = 30_000;
|
|
47
|
+
const PHASE_TIMEOUT_MAX_MS = 60 * 60 * 1000;
|
|
48
|
+
const PhaseTimeoutSchema = zod_1.z
|
|
49
|
+
.number()
|
|
50
|
+
.int()
|
|
51
|
+
.min(PHASE_TIMEOUT_MIN_MS)
|
|
52
|
+
.max(PHASE_TIMEOUT_MAX_MS)
|
|
53
|
+
.optional();
|
|
54
|
+
const lineageEnum = zod_1.z.enum(['anthropic', 'openai', 'google', 'opencode', 'moonshot', 'openrouter', 'any']);
|
|
55
|
+
const reviewerLineageEnum = zod_1.z.enum(['anthropic', 'openai', 'google', 'opencode', 'moonshot', 'openrouter']);
|
|
56
|
+
const ReviewerSchema = zod_1.z.object({
|
|
57
|
+
require: zod_1.z.number().int().min(0).default(1),
|
|
58
|
+
crossLineage: zod_1.z.boolean().default(true),
|
|
59
|
+
candidates: zod_1.z.array(zod_1.z.object({
|
|
60
|
+
lineage: reviewerLineageEnum,
|
|
61
|
+
models: zod_1.z.array(zod_1.z.string()).optional(),
|
|
62
|
+
/**
|
|
63
|
+
* Optional persona id. When set, the runner prepends the persona's
|
|
64
|
+
* `system_prompt` (looked up from the personas table at runtime) to
|
|
65
|
+
* the reviewer's ask.md so this slot reviews from a specific
|
|
66
|
+
* worldview — e.g. `sentinel` (security), `cartographer`
|
|
67
|
+
* (cross-platform), `translator` (UX).
|
|
68
|
+
*
|
|
69
|
+
* Lookup is lazy: an unknown id parses fine here but the runner
|
|
70
|
+
* silently falls back to the no-persona prompt rather than failing
|
|
71
|
+
* the run. Validation that a personaId resolves is the cockpit's
|
|
72
|
+
* job (the picker only offers ids that exist).
|
|
73
|
+
*/
|
|
74
|
+
persona: zod_1.z.string().optional(),
|
|
75
|
+
})),
|
|
76
|
+
});
|
|
77
|
+
const InputsSchema = zod_1.z.object({
|
|
78
|
+
include: zod_1.z.array(zod_1.z.string()).default([]),
|
|
79
|
+
exclude: zod_1.z.array(zod_1.z.string()).default([]),
|
|
80
|
+
}).default({ include: [], exclude: [] });
|
|
81
|
+
const IterateSchema = zod_1.z.object({
|
|
82
|
+
maxRounds: zod_1.z.number().int().min(1).default(2),
|
|
83
|
+
onDisagreement: zod_1.z.enum(['continue', 'escalate', 'accept-doer']).default('continue'),
|
|
84
|
+
// Reuse the same tmux session across rounds 1..N of THIS phase.
|
|
85
|
+
// Default true = save tokens (LLM keeps context in its session).
|
|
86
|
+
// Set false when a fresh perspective per round matters more than cost.
|
|
87
|
+
shareSessionAcrossRounds: zod_1.z.boolean().default(true),
|
|
88
|
+
// Reuse this phase's tmux session for the NEXT phase too.
|
|
89
|
+
// Default false = fresh session per phase boundary (different artifacts).
|
|
90
|
+
// Rare to enable; only when phases are tightly coupled and context-sharing helps.
|
|
91
|
+
shareSessionAcrossPhases: zod_1.z.boolean().default(false),
|
|
92
|
+
}).default({
|
|
93
|
+
maxRounds: 2,
|
|
94
|
+
onDisagreement: 'continue',
|
|
95
|
+
shareSessionAcrossRounds: true,
|
|
96
|
+
shareSessionAcrossPhases: false,
|
|
97
|
+
});
|
|
98
|
+
/**
|
|
99
|
+
* Standard phase: doer + optional reviewers + iterate loop.
|
|
100
|
+
*/
|
|
101
|
+
const StandardPhaseSchema = zod_1.z.object({
|
|
102
|
+
id: zod_1.z.string().min(1),
|
|
103
|
+
kind: zod_1.z.enum(['plan', 'spec', 'tests', 'implement', 'review', 'verify', 'divergence']),
|
|
104
|
+
title: zod_1.z.string().min(1),
|
|
105
|
+
description: zod_1.z.string().optional(),
|
|
106
|
+
doer: zod_1.z.object({
|
|
107
|
+
lineage: lineageEnum,
|
|
108
|
+
models: zod_1.z.array(zod_1.z.string()).optional(),
|
|
109
|
+
/**
|
|
110
|
+
* Optional persona id. Same semantics as on reviewer candidates —
|
|
111
|
+
* persona.system_prompt prepends the doer's ask. Lets a template
|
|
112
|
+
* say "build this with a security-first worldview" instead of
|
|
113
|
+
* leaving worldview implicit in the doer model.
|
|
114
|
+
*/
|
|
115
|
+
persona: zod_1.z.string().optional(),
|
|
116
|
+
}),
|
|
117
|
+
reviewer: ReviewerSchema.optional(),
|
|
118
|
+
inputs: InputsSchema,
|
|
119
|
+
iterate: IterateSchema,
|
|
120
|
+
/**
|
|
121
|
+
* Optional hard wait budget for both the doer subprocess and each
|
|
122
|
+
* reviewer subprocess in this phase. When unset, the runner falls back
|
|
123
|
+
* to DEFAULT_PHASE_TIMEOUT_MS. Bounds: 30s ≤ timeoutMs ≤ 1h.
|
|
124
|
+
*/
|
|
125
|
+
timeoutMs: PhaseTimeoutSchema,
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* Review-only phase: artifact supplied at runtime, no doer, single pass.
|
|
129
|
+
*
|
|
130
|
+
* The `artifact` block carries cockpit hints (label, hint placeholder) and
|
|
131
|
+
* a hard size cap that the chat-create endpoint enforces. iterate is
|
|
132
|
+
* deliberately omitted — review-only is always one round, and surfacing
|
|
133
|
+
* iterate would imply the runner could loop, which it can't.
|
|
134
|
+
*/
|
|
135
|
+
const ReviewOnlyPhaseSchema = zod_1.z.object({
|
|
136
|
+
id: zod_1.z.string().min(1),
|
|
137
|
+
kind: zod_1.z.literal('review_only'),
|
|
138
|
+
title: zod_1.z.string().min(1),
|
|
139
|
+
description: zod_1.z.string().optional(),
|
|
140
|
+
reviewer: ReviewerSchema,
|
|
141
|
+
artifact: zod_1.z.object({
|
|
142
|
+
label: zod_1.z.string().min(1).default('Artifact to review'),
|
|
143
|
+
hint: zod_1.z.string().default('Paste a unified diff, a markdown draft, code, or any text blob.'),
|
|
144
|
+
// 1 MiB default cap. Anything larger is rejected at chat-create time.
|
|
145
|
+
maxBytes: zod_1.z.number().int().min(1).default(1024 * 1024),
|
|
146
|
+
}).default({
|
|
147
|
+
label: 'Artifact to review',
|
|
148
|
+
hint: 'Paste a unified diff, a markdown draft, code, or any text blob.',
|
|
149
|
+
maxBytes: 1024 * 1024,
|
|
150
|
+
}),
|
|
151
|
+
inputs: InputsSchema,
|
|
152
|
+
/** Same per-phase override as standard phases; applies to all reviewers. */
|
|
153
|
+
timeoutMs: PhaseTimeoutSchema,
|
|
154
|
+
});
|
|
155
|
+
exports.PhaseSchema = zod_1.z.discriminatedUnion('kind', [
|
|
156
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('plan') }),
|
|
157
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('spec') }),
|
|
158
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('tests') }),
|
|
159
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('implement') }),
|
|
160
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('review') }),
|
|
161
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('verify') }),
|
|
162
|
+
StandardPhaseSchema.extend({ kind: zod_1.z.literal('divergence') }),
|
|
163
|
+
ReviewOnlyPhaseSchema,
|
|
164
|
+
]);
|
|
165
|
+
/**
|
|
166
|
+
* Type guard: is this phase a review-only phase?
|
|
167
|
+
*
|
|
168
|
+
* Centralised so callers don't repeat the literal check. Also gives the
|
|
169
|
+
* compiler a narrowing hook so `phase.artifact` is type-safe inside the
|
|
170
|
+
* branch (and `phase.doer` is type-safe outside it).
|
|
171
|
+
*/
|
|
172
|
+
function isReviewOnlyPhase(phase) {
|
|
173
|
+
return phase.kind === 'review_only';
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* A built-in or user-authored template.
|
|
177
|
+
* Defines the workflow: phases, agreement threshold, and escalation policy.
|
|
178
|
+
*/
|
|
179
|
+
exports.TemplateSchema = zod_1.z.object({
|
|
180
|
+
id: zod_1.z.string().min(1),
|
|
181
|
+
name: zod_1.z.string().min(1),
|
|
182
|
+
description: zod_1.z.string().min(1),
|
|
183
|
+
author: zod_1.z.string().default('chorus'),
|
|
184
|
+
// Agreement policy
|
|
185
|
+
agreementThreshold: zod_1.z.number().min(0).max(1).default(0.66),
|
|
186
|
+
onThresholdMet: zod_1.z.enum(['merge', 'ask', 'review']).default('ask'),
|
|
187
|
+
maxRounds: zod_1.z.number().int().min(1).default(3),
|
|
188
|
+
// Runtime defaults
|
|
189
|
+
yoloDefault: zod_1.z.boolean().default(false),
|
|
190
|
+
/**
|
|
191
|
+
* Per-template approximation of the input-token boilerplate that goes
|
|
192
|
+
* into ONE reviewer's first round. Includes system prompt, persona
|
|
193
|
+
* block, and ask scaffolding that the daemon prepends before the
|
|
194
|
+
* user's artifact/work text. Used by the cockpit's pre-submit cost
|
|
195
|
+
* estimate; a heuristic, not a contract — actual usage depends on the
|
|
196
|
+
* shim's prompt-builder output.
|
|
197
|
+
*
|
|
198
|
+
* Defaults to 800 in the cockpit when a template doesn't declare a
|
|
199
|
+
* value (matches the previous hardcoded baseline). Templates with
|
|
200
|
+
* heavier scaffolding (multi-phase, dense persona text) should set
|
|
201
|
+
* this higher; lighter templates (review-only) lower.
|
|
202
|
+
*/
|
|
203
|
+
estimatedBaselineTokens: zod_1.z.number().int().min(0).optional(),
|
|
204
|
+
// The workflow phases.
|
|
205
|
+
//
|
|
206
|
+
// Hybrid templates (review_only mixed with standard phases) are explicitly
|
|
207
|
+
// out of scope for v0.5 — the chat-create endpoint only checks phases[0]
|
|
208
|
+
// when deciding whether `artifact` is required, so a non-first review_only
|
|
209
|
+
// phase would silently run with an empty artifact. Reject the shape at
|
|
210
|
+
// parse time instead of accepting it and producing garbage reviews.
|
|
211
|
+
phases: zod_1.z
|
|
212
|
+
.array(exports.PhaseSchema)
|
|
213
|
+
.min(1)
|
|
214
|
+
.refine((phases) => {
|
|
215
|
+
const reviewOnlyCount = phases.filter((p) => p.kind === 'review_only').length;
|
|
216
|
+
// Either all standard, or exactly one review_only that occupies the
|
|
217
|
+
// entire phase list. (No partial mix; no two review_only phases —
|
|
218
|
+
// multi-pass review-only is also out of scope.)
|
|
219
|
+
return reviewOnlyCount === 0 || (reviewOnlyCount === 1 && phases.length === 1);
|
|
220
|
+
}, {
|
|
221
|
+
message: 'review_only phases cannot be mixed with other phase kinds and only one is allowed (hybrid templates are out of scope)',
|
|
222
|
+
})
|
|
223
|
+
.refine((phases) => {
|
|
224
|
+
// Phase IDs are referenced from the runner (phase_events.phase_id,
|
|
225
|
+
// chat dir layout, gate keys). Duplicates would clobber each other.
|
|
226
|
+
const ids = phases.map((p) => p.id);
|
|
227
|
+
return new Set(ids).size === ids.length;
|
|
228
|
+
}, {
|
|
229
|
+
message: 'phase ids must be unique',
|
|
230
|
+
}),
|
|
231
|
+
/**
|
|
232
|
+
* Optional Ship phase — runs after all phases pass + reviewers agree.
|
|
233
|
+
*
|
|
234
|
+
* When `enabled: true` AND the chat was created with `repoPath`:
|
|
235
|
+
* 1. Verify git context (gh CLI installed/authed, repoPath is a repo
|
|
236
|
+
* with a remote, base branch resolvable)
|
|
237
|
+
* 2. Stage + commit doer's diff with a message from the chat
|
|
238
|
+
* 3. Push the chorus branch
|
|
239
|
+
* 4. `gh pr create` against baseBranch
|
|
240
|
+
* 5. Stop. No auto-merge in v0.5 — human clicks Merge in GitHub UI.
|
|
241
|
+
*
|
|
242
|
+
* When `enabled: false` OR chat has no repoPath: phase is skipped,
|
|
243
|
+
* chat ends with status=approved as before. No noise.
|
|
244
|
+
*
|
|
245
|
+
* On any failure (gh missing, push reject, dirty working tree, etc.):
|
|
246
|
+
* chat ends with status=blocked and the failure mode in the meta.
|
|
247
|
+
*
|
|
248
|
+
* Note: a template whose first phase is `review_only` cannot ship — the
|
|
249
|
+
* runner skips ship for those regardless of this flag (no doer diff
|
|
250
|
+
* exists). The flag is allowed in the YAML so a template author can
|
|
251
|
+
* write the field without the validator rejecting it; the runner is
|
|
252
|
+
* the enforcement point.
|
|
253
|
+
*/
|
|
254
|
+
ship: zod_1.z
|
|
255
|
+
.object({
|
|
256
|
+
enabled: zod_1.z.boolean().default(false),
|
|
257
|
+
/** Base branch to PR against. If unset, ship.ts detects default branch. */
|
|
258
|
+
baseBranch: zod_1.z.string().optional(),
|
|
259
|
+
/** Branch name pattern. {chatId} is substituted. */
|
|
260
|
+
branchPattern: zod_1.z.string().default('chorus/{chatId}'),
|
|
261
|
+
/** PR title template. {template} {chatId} substituted. */
|
|
262
|
+
titleTemplate: zod_1.z.string().default('chorus: {template} via #{chatId}'),
|
|
263
|
+
})
|
|
264
|
+
.optional(),
|
|
265
|
+
/**
|
|
266
|
+
* Template-level fallback voices. Tried in order whenever a slot
|
|
267
|
+
* exhausts its own per-slot model chain (`candidate.models[]`) without
|
|
268
|
+
* producing an answer.
|
|
269
|
+
*
|
|
270
|
+
* Split by role so authors can tune doer-failure recovery independently
|
|
271
|
+
* from reviewer-failure recovery — typical case: a Sonnet/Haiku ladder
|
|
272
|
+
* for doer (cheap, fast) but a different lineage entirely for reviewer
|
|
273
|
+
* fallback (diversity preservation).
|
|
274
|
+
*
|
|
275
|
+
* Dedupe rule (strict, by lineage+model, scoped per-phase per-role):
|
|
276
|
+
* - Skip if the candidate matches the failed slot itself (would just
|
|
277
|
+
* fail again).
|
|
278
|
+
* - Skip if the candidate matches any OTHER active slot of the same
|
|
279
|
+
* role in the same phase (e.g. reviewers=[kimi, deepseek] with
|
|
280
|
+
* fallback.reviewer=[kimi] → don't raise a second kimi reviewer).
|
|
281
|
+
*
|
|
282
|
+
* Each entry is a single voice. Authors who want a multi-model fallback
|
|
283
|
+
* chain put them as separate rows in priority order. Same-lineage only
|
|
284
|
+
* for v0.7 (cross-lineage swap is a bigger feature; out of scope).
|
|
285
|
+
*/
|
|
286
|
+
fallback: zod_1.z
|
|
287
|
+
.object({
|
|
288
|
+
doer: zod_1.z
|
|
289
|
+
.array(zod_1.z.object({
|
|
290
|
+
lineage: lineageEnum,
|
|
291
|
+
models: zod_1.z.array(zod_1.z.string()).min(1),
|
|
292
|
+
persona: zod_1.z.string().optional(),
|
|
293
|
+
}))
|
|
294
|
+
.optional(),
|
|
295
|
+
reviewer: zod_1.z
|
|
296
|
+
.array(zod_1.z.object({
|
|
297
|
+
lineage: reviewerLineageEnum,
|
|
298
|
+
models: zod_1.z.array(zod_1.z.string()).min(1),
|
|
299
|
+
persona: zod_1.z.string().optional(),
|
|
300
|
+
}))
|
|
301
|
+
.optional(),
|
|
302
|
+
})
|
|
303
|
+
.optional(),
|
|
304
|
+
});
|
|
305
|
+
/**
|
|
306
|
+
* Convenience: does the template's first phase require a runtime artifact?
|
|
307
|
+
*
|
|
308
|
+
* Used by the chat-create endpoint to gate the `artifact` body field and by
|
|
309
|
+
* cockpit/CLI surfaces to swap UI between "task" and "artifact" affordances.
|
|
310
|
+
*
|
|
311
|
+
* NOTE: only the first phase is consulted. Hybrid templates (some phases
|
|
312
|
+
* review_only, some not) are out of scope for v0.5 and would need a richer
|
|
313
|
+
* answer.
|
|
314
|
+
*/
|
|
315
|
+
function templateRequiresArtifact(template) {
|
|
316
|
+
const first = template.phases[0];
|
|
317
|
+
return first ? isReviewOnlyPhase(first) : false;
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=template-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-schema.js","sourceRoot":"","sources":["../../src/lib/template-schema.ts"],"names":[],"mappings":"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"}
|