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,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerStartCommand = registerStartCommand;
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const open_1 = __importDefault(require("open"));
|
|
10
|
+
const os_1 = __importDefault(require("os"));
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
12
|
+
const port_utils_js_1 = require("../port-utils.js");
|
|
13
|
+
const runtime_env_js_1 = require("../runtime-env.js");
|
|
14
|
+
const shared_js_1 = require("../shared.js");
|
|
15
|
+
const ui_js_1 = require("../ui.js");
|
|
16
|
+
function registerStartCommand(program) {
|
|
17
|
+
program
|
|
18
|
+
.command('start')
|
|
19
|
+
.option('--ui', 'Open browser UI after starting daemon')
|
|
20
|
+
.description('Start the Chorus daemon (PM2-style fork)')
|
|
21
|
+
.action(async (options) => {
|
|
22
|
+
try {
|
|
23
|
+
const chorusDir = path_1.default.join(os_1.default.homedir(), '.chorus');
|
|
24
|
+
const pidFile = path_1.default.join(chorusDir, 'daemon.pid');
|
|
25
|
+
if (await alreadyRunning(pidFile, options.ui))
|
|
26
|
+
return;
|
|
27
|
+
if (await alreadyRunningOnDefaultPort(options.ui))
|
|
28
|
+
return;
|
|
29
|
+
await reapOrphans();
|
|
30
|
+
warnIfTmuxMissing();
|
|
31
|
+
// Capture the interactive PATH from the user's terminal BEFORE
|
|
32
|
+
// forking the daemon. The daemon's own spawn loses this — it
|
|
33
|
+
// runs from a non-interactive shell that skips ~/.bashrc, so
|
|
34
|
+
// tools installed to ~/.opencode/bin etc. would be missing.
|
|
35
|
+
// Re-capturing on every start (not just init) means a user who
|
|
36
|
+
// adds a new tool to PATH and restarts picks it up automatically.
|
|
37
|
+
await captureAndPersistPath();
|
|
38
|
+
spawnDaemonAndCockpit(chorusDir, pidFile);
|
|
39
|
+
scheduleAutoOpenBrowser(options.ui);
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.error('Failed to start daemon:', error);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Run the user's interactive shell once and stash $PATH so the daemon
|
|
49
|
+
* (running in a non-interactive shell that skips .bashrc/.zshrc) can
|
|
50
|
+
* find CLIs the user installed via official curl-bash scripts.
|
|
51
|
+
*
|
|
52
|
+
* Best-effort. Capture or persist failures are swallowed — the daemon
|
|
53
|
+
* has fallback known-install probes and the previous saved value, if
|
|
54
|
+
* any, stays put.
|
|
55
|
+
*/
|
|
56
|
+
async function captureAndPersistPath() {
|
|
57
|
+
try {
|
|
58
|
+
const { captureInteractivePath, persistCapturedPath } = await import('../../lib/runtime-path.js');
|
|
59
|
+
const captured = captureInteractivePath();
|
|
60
|
+
if (captured)
|
|
61
|
+
await persistCapturedPath(captured);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
/* non-fatal */
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Pidfile-less variant of `alreadyRunning`. Covers the case where
|
|
69
|
+
* the daemon is healthy on :7707 but the pidfile is missing or stale
|
|
70
|
+
* (manual deletion, /tmp wipe, prior crash before pidfile write,
|
|
71
|
+
* sudo-started daemon vs. user-invoked `chorus start`, etc.).
|
|
72
|
+
*
|
|
73
|
+
* Without this, a healthy chorus + missing pidfile would fall through
|
|
74
|
+
* to reapOrphans() and either kill the live daemon or hit the
|
|
75
|
+
* "couldn't identify the PID" dead-end (when the daemon runs as a
|
|
76
|
+
* different user and `ss -p` redacts the PID).
|
|
77
|
+
*
|
|
78
|
+
* The HTTP probe alone is a strong signal — chorus's /api/v1/health
|
|
79
|
+
* returns a versioned envelope no random other process happens to
|
|
80
|
+
* mimic. The PID-cmdline cross-check is belt-and-braces: only treat
|
|
81
|
+
* "already running" as authoritative when both agree it's chorus.
|
|
82
|
+
*/
|
|
83
|
+
async function alreadyRunningOnDefaultPort(uiFlag) {
|
|
84
|
+
// Short timeout — we're trying to fail fast and fall through to reap
|
|
85
|
+
// logic when the daemon is actually dead. 1.5s covers a slow loopback
|
|
86
|
+
// round-trip on resource-starved CI runners without making a healthy
|
|
87
|
+
// system feel sluggish.
|
|
88
|
+
let healthyVersion = null;
|
|
89
|
+
try {
|
|
90
|
+
const ac = new AbortController();
|
|
91
|
+
const timer = setTimeout(() => ac.abort(), 1500);
|
|
92
|
+
const res = await fetch(`${shared_js_1.DAEMON_URL}/api/v1/health`, {
|
|
93
|
+
signal: ac.signal,
|
|
94
|
+
});
|
|
95
|
+
clearTimeout(timer);
|
|
96
|
+
if (!res.ok)
|
|
97
|
+
return false;
|
|
98
|
+
const envelope = (await res.json());
|
|
99
|
+
if (envelope.ok !== true || !envelope.data?.version)
|
|
100
|
+
return false;
|
|
101
|
+
healthyVersion = envelope.data.version;
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// ECONNREFUSED / abort / parse error → not a healthy chorus on :7707.
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
// Cross-check: the PID listening on :7707 must look like chorus.
|
|
108
|
+
// Without this, a foreign service that happens to respond 200 on
|
|
109
|
+
// /api/v1/health with a matching envelope shape could fool us into
|
|
110
|
+
// sending the user to a wrong cockpit URL. Belt-and-braces.
|
|
111
|
+
const pids = (0, port_utils_js_1.findPidsOnPort)(7707);
|
|
112
|
+
const looksLikeChorus = pids.some((pid) => (0, port_utils_js_1.pidLooksLikeChorus)(pid).match);
|
|
113
|
+
if (pids.length > 0 && !looksLikeChorus)
|
|
114
|
+
return false;
|
|
115
|
+
console.log('');
|
|
116
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.ok, 'Chorus is already running', `version ${healthyVersion}`));
|
|
117
|
+
(0, shared_js_1.printCockpitAccessHint)();
|
|
118
|
+
if (uiFlag && (0, runtime_env_js_1.shouldAutoOpenBrowser)((0, runtime_env_js_1.detectRuntimeEnv)())) {
|
|
119
|
+
(0, open_1.default)(shared_js_1.COCKPIT_URL);
|
|
120
|
+
}
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
async function alreadyRunning(pidFile, uiFlag) {
|
|
124
|
+
if (!fs_1.default.existsSync(pidFile))
|
|
125
|
+
return false;
|
|
126
|
+
const oldPid = parseInt(fs_1.default.readFileSync(pidFile, 'utf-8'), 10);
|
|
127
|
+
try {
|
|
128
|
+
// Cross-platform liveness probe. process.kill(pid, 0) throws if no
|
|
129
|
+
// process with that pid exists; works on Windows/macOS/Linux unlike
|
|
130
|
+
// the unix-only `kill -0` shell command we used to invoke here.
|
|
131
|
+
if (Number.isFinite(oldPid) && oldPid > 0) {
|
|
132
|
+
process.kill(oldPid, 0);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
throw new Error('invalid pid');
|
|
136
|
+
}
|
|
137
|
+
console.log('');
|
|
138
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.ok, 'Chorus is already running', `daemon PID ${oldPid}`));
|
|
139
|
+
(0, shared_js_1.printCockpitAccessHint)();
|
|
140
|
+
if (uiFlag && (0, runtime_env_js_1.shouldAutoOpenBrowser)((0, runtime_env_js_1.detectRuntimeEnv)())) {
|
|
141
|
+
(0, open_1.default)(shared_js_1.COCKPIT_URL);
|
|
142
|
+
}
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Process doesn't exist, clean up the stale pidfile.
|
|
147
|
+
fs_1.default.unlinkSync(pidFile);
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Pre-spawn orphan reap. Pidfile-based liveness only catches the
|
|
153
|
+
* recorded daemon PID — it misses a stale next-server (cockpit) or
|
|
154
|
+
* daemon that survived a previous `chorus stop` because the SIGTERM
|
|
155
|
+
* was ignored or the pidfile got out of sync. Without this sweep, a
|
|
156
|
+
* fresh `chorus start` would race against the orphan on :5050 / :7707,
|
|
157
|
+
* the new spawn would lose, and the user would see 500s served by the
|
|
158
|
+
* ghost (incident 2026-05-03).
|
|
159
|
+
*
|
|
160
|
+
* Foreign-process guard: only reap PIDs whose cmdline looks like a
|
|
161
|
+
* chorus daemon/cockpit. If something else (Grafana on :5050, a
|
|
162
|
+
* colleague's `next dev` on :7707) is bound, refuse to kill it and ask
|
|
163
|
+
* the user to free the port. Pre-fix the reaper would silently SIGKILL
|
|
164
|
+
* whatever it found.
|
|
165
|
+
*/
|
|
166
|
+
async function reapOrphans() {
|
|
167
|
+
for (const [port, label] of [
|
|
168
|
+
[7707, 'daemon'],
|
|
169
|
+
[5050, 'cockpit'],
|
|
170
|
+
]) {
|
|
171
|
+
if (!(await (0, port_utils_js_1.isPortInUse)(port)))
|
|
172
|
+
continue;
|
|
173
|
+
const pids = (0, port_utils_js_1.findPidsOnPort)(port);
|
|
174
|
+
if (pids.length === 0) {
|
|
175
|
+
console.log('');
|
|
176
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.err, `Port :${port} is in use by another process`, `couldn't identify the PID — free the port and retry`));
|
|
177
|
+
console.log('');
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
for (const pid of pids) {
|
|
181
|
+
const { match, cmdline } = (0, port_utils_js_1.pidLooksLikeChorus)(pid);
|
|
182
|
+
if (!match) {
|
|
183
|
+
console.log('');
|
|
184
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.err, `Port :${port} is in use by a non-chorus process`, `PID ${pid}: ${cmdline ?? '(unreadable)'}`));
|
|
185
|
+
console.log('');
|
|
186
|
+
console.log((0, ui_js_1.tip)(label === 'daemon'
|
|
187
|
+
? `Free :${port} (stop the other process, or relocate the daemon via CHORUS_DAEMON_PORT) and retry \`chorus start\`.`
|
|
188
|
+
: `Free :${port} (stop the other process listening on the cockpit port) and retry \`chorus start\`.`));
|
|
189
|
+
console.log('');
|
|
190
|
+
process.exit(1);
|
|
191
|
+
}
|
|
192
|
+
const dead = await (0, port_utils_js_1.killAndVerify)(pid, `${label} orphan`);
|
|
193
|
+
if (dead) {
|
|
194
|
+
console.log(` ${ui_js_1.sym.ok} reaped ${label} orphan on :${port} ${ui_js_1.c.dim(`(PID ${pid})`)}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Default transport is 'headless' (no tmux needed). tmux is the
|
|
201
|
+
* OPTIONAL backup mode for users who want to attach to a live voice
|
|
202
|
+
* session and take over / watch step-by-step / hand off mid-run.
|
|
203
|
+
* Surfaced once at start so power users know the feature exists.
|
|
204
|
+
* Soft-info (not a warning) so we don't scare default-path users.
|
|
205
|
+
*/
|
|
206
|
+
function warnIfTmuxMissing() {
|
|
207
|
+
try {
|
|
208
|
+
(0, child_process_1.execFileSync)('tmux', ['-V'], { stdio: 'ignore' });
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
console.log('');
|
|
212
|
+
console.log(ui_js_1.c.dim(` ${ui_js_1.sym.info} tmux not detected. Chorus runs headless by default — this is fine.`));
|
|
213
|
+
console.log(ui_js_1.c.dim(' Optional backup mode: install tmux, then open'));
|
|
214
|
+
console.log(ui_js_1.c.dim(' http://127.0.0.1:5050/settings#transport and pick "Tmux — attach & take over".'));
|
|
215
|
+
console.log(ui_js_1.c.dim(' `tmux attach -t <name>` lets you watch step-by-step or take over mid-run.'));
|
|
216
|
+
console.log(ui_js_1.c.dim(' macOS: brew install tmux · Ubuntu/Debian: apt install tmux · Fedora: dnf install tmux'));
|
|
217
|
+
console.log('');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function spawnDaemonAndCockpit(chorusDir, pidFile) {
|
|
221
|
+
// Prefer the compiled JS so a global install works (no src/ shipped,
|
|
222
|
+
// no tsx loader registered); fall back to the .ts source when running
|
|
223
|
+
// in dev mode where the user only has src/ on disk.
|
|
224
|
+
const daemonJs = path_1.default.resolve(__dirname, '..', '..', 'daemon', 'index.js');
|
|
225
|
+
const daemonTs = path_1.default.resolve(__dirname, '..', '..', '..', 'src', 'daemon', 'index.ts');
|
|
226
|
+
const useCompiled = fs_1.default.existsSync(daemonJs);
|
|
227
|
+
const daemonPath = useCompiled ? daemonJs : daemonTs;
|
|
228
|
+
const spawnArgs = useCompiled ? [daemonPath] : ['-r', 'tsx/cjs', daemonPath];
|
|
229
|
+
// Pipe daemon stdout + stderr to a log file so the user (and we, when
|
|
230
|
+
// debugging) can see why a chat went sideways. Previously stdio was
|
|
231
|
+
// 'ignore' which made silent failures impossible to diagnose. Logs
|
|
232
|
+
// rotate manually; truncated to 10 MB max via periodic rotate inside
|
|
233
|
+
// the daemon (TODO).
|
|
234
|
+
fs_1.default.mkdirSync(chorusDir, { recursive: true });
|
|
235
|
+
const logsDir = path_1.default.join(chorusDir, 'logs');
|
|
236
|
+
fs_1.default.mkdirSync(logsDir, { recursive: true });
|
|
237
|
+
const daemonLogPath = path_1.default.join(logsDir, 'daemon.log');
|
|
238
|
+
const daemonLogFd = fs_1.default.openSync(daemonLogPath, 'a');
|
|
239
|
+
const child = (0, child_process_1.spawn)('node', spawnArgs, {
|
|
240
|
+
detached: true,
|
|
241
|
+
stdio: ['ignore', daemonLogFd, daemonLogFd],
|
|
242
|
+
});
|
|
243
|
+
if (!child.pid) {
|
|
244
|
+
throw new Error('Failed to spawn daemon process');
|
|
245
|
+
}
|
|
246
|
+
fs_1.default.writeFileSync(pidFile, child.pid.toString());
|
|
247
|
+
// Spawn the cockpit web UI alongside the daemon. The package ships a
|
|
248
|
+
// built .next directory; run next from the package root so it picks
|
|
249
|
+
// up the bundled bun_modules. Web PID is tracked separately so
|
|
250
|
+
// `chorus stop` can clean up both.
|
|
251
|
+
const packageRoot = path_1.default.resolve(__dirname, '..', '..', '..');
|
|
252
|
+
const nextEntry = path_1.default.resolve(packageRoot, 'node_modules', 'next', 'dist', 'bin', 'next');
|
|
253
|
+
const webPidFile = path_1.default.join(chorusDir, 'web.pid');
|
|
254
|
+
if (fs_1.default.existsSync(nextEntry) &&
|
|
255
|
+
fs_1.default.existsSync(path_1.default.join(packageRoot, '.next'))) {
|
|
256
|
+
const webLogPath = path_1.default.join(logsDir, 'web.log');
|
|
257
|
+
const webLogFd = fs_1.default.openSync(webLogPath, 'a');
|
|
258
|
+
const webChild = (0, child_process_1.spawn)('node', [nextEntry, 'start', '-p', '5050', '-H', '127.0.0.1'], {
|
|
259
|
+
cwd: packageRoot,
|
|
260
|
+
detached: true,
|
|
261
|
+
stdio: ['ignore', webLogFd, webLogFd],
|
|
262
|
+
});
|
|
263
|
+
if (webChild.pid) {
|
|
264
|
+
fs_1.default.writeFileSync(webPidFile, webChild.pid.toString());
|
|
265
|
+
webChild.unref();
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
// Loud, actionable error — the previous yellow warning was easy to
|
|
270
|
+
// miss and left users at a blank cockpit URL with no idea why. We
|
|
271
|
+
// keep the daemon running (MCP + API still work) but make the
|
|
272
|
+
// remediation steps obvious.
|
|
273
|
+
console.log('');
|
|
274
|
+
console.log(ui_js_1.c.red(' ✗ Cockpit UI not found.'));
|
|
275
|
+
if (fs_1.default.existsSync(path_1.default.join(packageRoot, 'src'))) {
|
|
276
|
+
console.log(ui_js_1.c.dim(' This looks like a dev checkout. Build it once:'));
|
|
277
|
+
console.log(` ${ui_js_1.c.bold('pnpm install && pnpm build')}`);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
console.log(ui_js_1.c.dim(' The published install should ship a built UI. Try reinstalling:'));
|
|
281
|
+
console.log(` ${ui_js_1.c.bold('npm install -g chorus-codes')}`);
|
|
282
|
+
}
|
|
283
|
+
console.log(ui_js_1.c.dim(' The daemon API is still up on port 7707 if you only need MCP.'));
|
|
284
|
+
console.log('');
|
|
285
|
+
}
|
|
286
|
+
child.unref();
|
|
287
|
+
console.log('');
|
|
288
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.ok, 'Chorus started', `daemon PID ${child.pid}`));
|
|
289
|
+
(0, shared_js_1.printCockpitAccessHint)();
|
|
290
|
+
}
|
|
291
|
+
function scheduleAutoOpenBrowser(uiFlag) {
|
|
292
|
+
setTimeout(() => {
|
|
293
|
+
if (uiFlag && (0, runtime_env_js_1.shouldAutoOpenBrowser)((0, runtime_env_js_1.detectRuntimeEnv)())) {
|
|
294
|
+
(0, open_1.default)(shared_js_1.COCKPIT_URL);
|
|
295
|
+
}
|
|
296
|
+
}, 1000);
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerStatusCommand = registerStatusCommand;
|
|
4
|
+
const shared_js_1 = require("../shared.js");
|
|
5
|
+
const ui_js_1 = require("../ui.js");
|
|
6
|
+
function registerStatusCommand(program) {
|
|
7
|
+
program
|
|
8
|
+
.command('status')
|
|
9
|
+
.description('Check daemon health')
|
|
10
|
+
.action(async () => {
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetch(`${shared_js_1.DAEMON_URL}/api/v1/health`);
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
console.log('');
|
|
15
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.err, 'Daemon is not running', 'start with `chorus start`'));
|
|
16
|
+
console.log('');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const envelope = (await response.json());
|
|
20
|
+
const data = envelope.data;
|
|
21
|
+
if (envelope.ok && data) {
|
|
22
|
+
const uptime = Math.floor(data.uptime / 1000);
|
|
23
|
+
const human = uptime < 60
|
|
24
|
+
? `${uptime}s`
|
|
25
|
+
: uptime < 3600
|
|
26
|
+
? `${Math.floor(uptime / 60)}m`
|
|
27
|
+
: `${Math.floor(uptime / 3600)}h ${Math.floor((uptime % 3600) / 60)}m`;
|
|
28
|
+
console.log('');
|
|
29
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.ok, 'Chorus is running'));
|
|
30
|
+
console.log('');
|
|
31
|
+
console.log((0, ui_js_1.kv)([
|
|
32
|
+
['Version', ui_js_1.c.cyan(data.version)],
|
|
33
|
+
['Uptime', ui_js_1.c.dim(human)],
|
|
34
|
+
['Cockpit', ui_js_1.c.cyan(shared_js_1.COCKPIT_URL)],
|
|
35
|
+
['Daemon', ui_js_1.c.dim(shared_js_1.DAEMON_URL)],
|
|
36
|
+
]));
|
|
37
|
+
console.log('');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log('');
|
|
41
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.err, 'Daemon is not responding correctly'));
|
|
42
|
+
console.log('');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
console.log('');
|
|
48
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.err, 'Daemon is not running', 'start with `chorus start`'));
|
|
49
|
+
console.log('');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerStopCommand = registerStopCommand;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const os_1 = __importDefault(require("os"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const port_utils_js_1 = require("../port-utils.js");
|
|
11
|
+
const ui_js_1 = require("../ui.js");
|
|
12
|
+
/**
|
|
13
|
+
* Two-stage shutdown per managed process: SIGTERM, wait up to 1.5s,
|
|
14
|
+
* escalate to SIGKILL if still alive. Don't unlink the pidfile until
|
|
15
|
+
* the process is confirmed dead — otherwise an orphan that ignores
|
|
16
|
+
* SIGTERM keeps running while we forget about it (the bug behind the
|
|
17
|
+
* "stale next-server serving 500s" incident on 2026-05-03).
|
|
18
|
+
*
|
|
19
|
+
* Belt-and-braces: after pidfile-based shutdown, also sweep ports
|
|
20
|
+
* :7707 (daemon) and :5050 (cockpit). Catches the case where the
|
|
21
|
+
* pidfile was lost or pointed at a recycled PID but a real chorus
|
|
22
|
+
* process still owns the port.
|
|
23
|
+
*/
|
|
24
|
+
function registerStopCommand(program) {
|
|
25
|
+
program
|
|
26
|
+
.command('stop')
|
|
27
|
+
.description('Stop the Chorus daemon and cockpit')
|
|
28
|
+
.action(async () => {
|
|
29
|
+
try {
|
|
30
|
+
const chorusDir = path_1.default.join(os_1.default.homedir(), '.chorus');
|
|
31
|
+
const daemonPidFile = path_1.default.join(chorusDir, 'daemon.pid');
|
|
32
|
+
const webPidFile = path_1.default.join(chorusDir, 'web.pid');
|
|
33
|
+
const daemonPidfileExists = fs_1.default.existsSync(daemonPidFile);
|
|
34
|
+
const webPidfileExists = fs_1.default.existsSync(webPidFile);
|
|
35
|
+
const daemonPortInUse = await (0, port_utils_js_1.isPortInUse)(7707);
|
|
36
|
+
const cockpitPortInUse = await (0, port_utils_js_1.isPortInUse)(5050);
|
|
37
|
+
if (!daemonPidfileExists &&
|
|
38
|
+
!webPidfileExists &&
|
|
39
|
+
!daemonPortInUse &&
|
|
40
|
+
!cockpitPortInUse) {
|
|
41
|
+
console.log('');
|
|
42
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.info, 'Chorus is not running', 'nothing to stop'));
|
|
43
|
+
console.log('');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
console.log('');
|
|
47
|
+
console.log((0, ui_js_1.header)(ui_js_1.sym.pointer, 'Stopping Chorus...'));
|
|
48
|
+
console.log('');
|
|
49
|
+
await stopProcess('Daemon', daemonPidFile);
|
|
50
|
+
await stopProcess('Cockpit', webPidFile);
|
|
51
|
+
// Port-based sweep — kills any chorus-owned listener that
|
|
52
|
+
// escaped the pidfile path. Errs on the side of cleanup;
|
|
53
|
+
// running a non-chorus service on these ports while invoking
|
|
54
|
+
// `chorus stop` is unsupported.
|
|
55
|
+
await sweepPort(7707, 'Daemon');
|
|
56
|
+
await sweepPort(5050, 'Cockpit');
|
|
57
|
+
console.log('');
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error(`${ui_js_1.sym.err} ${ui_js_1.c.red('Error stopping chorus:')}`, error);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async function stopProcess(label, pidFile) {
|
|
66
|
+
if (!fs_1.default.existsSync(pidFile))
|
|
67
|
+
return;
|
|
68
|
+
const pid = parseInt(fs_1.default.readFileSync(pidFile, 'utf-8'), 10);
|
|
69
|
+
if (!Number.isFinite(pid) || pid <= 0) {
|
|
70
|
+
fs_1.default.unlinkSync(pidFile);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const dead = await (0, port_utils_js_1.killAndVerify)(pid, label);
|
|
74
|
+
if (dead) {
|
|
75
|
+
console.log(` ${ui_js_1.sym.ok} ${label.padEnd(7)} ${ui_js_1.c.dim(`(PID ${pid})`)}`);
|
|
76
|
+
// Only unlink once we've confirmed the process is gone. Earlier
|
|
77
|
+
// code unconditionally unlinked, which orphaned any process that
|
|
78
|
+
// ignored SIGTERM — its successor `chorus start` couldn't see
|
|
79
|
+
// the ghost owner of the port.
|
|
80
|
+
try {
|
|
81
|
+
fs_1.default.unlinkSync(pidFile);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* already gone */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
async function sweepPort(port, label) {
|
|
89
|
+
const pids = (0, port_utils_js_1.findPidsOnPort)(port);
|
|
90
|
+
for (const pid of pids) {
|
|
91
|
+
const dead = await (0, port_utils_js_1.killAndVerify)(pid, `${label} orphan`);
|
|
92
|
+
if (dead) {
|
|
93
|
+
console.log(` ${ui_js_1.sym.ok} ${label.padEnd(7)} ${ui_js_1.c.dim(`(orphan PID ${pid} on :${port})`)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=stop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../../src/cli/commands/stop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `chorus connect [orchestrator]` — wire Chorus into a CLI's MCP config so
|
|
4
|
+
* the user can call chorus.* tools from inside it. Removes the per-tool
|
|
5
|
+
* "Yes, allow for this project?" friction (Claude) or registers the MCP
|
|
6
|
+
* server (Codex/Gemini/OpenCode) which they don't have until we add it.
|
|
7
|
+
*
|
|
8
|
+
* Idempotent. Same logic exposed at daemon `POST /orchestrators/:name/connect`
|
|
9
|
+
* so the cockpit's /connect page can run it with one click.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* chorus connect # all detected CLIs
|
|
13
|
+
* chorus connect claude # just Claude Code
|
|
14
|
+
* chorus connect codex,gemini # comma-separated subset
|
|
15
|
+
*/
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.runConnect = runConnect;
|
|
21
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
22
|
+
const index_js_1 = require("../daemon/orchestrators/index.js");
|
|
23
|
+
const CHORUS_BIN_PATH = node_path_1.default.resolve(__dirname, '..', '..', 'bin', 'chorus.mjs');
|
|
24
|
+
const ALL_NAMES = ['claude', 'codex', 'gemini', 'opencode', 'kimi', 'cursor', 'windsurf'];
|
|
25
|
+
function parseTargets(arg) {
|
|
26
|
+
if (!arg)
|
|
27
|
+
return null; // null = "all detected"
|
|
28
|
+
const wanted = arg.split(',').map((s) => s.trim().toLowerCase());
|
|
29
|
+
const valid = [];
|
|
30
|
+
for (const w of wanted) {
|
|
31
|
+
if (ALL_NAMES.includes(w)) {
|
|
32
|
+
valid.push(w);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.error(`Unknown orchestrator: '${w}'. Valid: ${ALL_NAMES.join(', ')}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return valid;
|
|
40
|
+
}
|
|
41
|
+
async function runConnect(orchestrator) {
|
|
42
|
+
const only = parseTargets(orchestrator);
|
|
43
|
+
const binPath = CHORUS_BIN_PATH;
|
|
44
|
+
console.log(`Connecting Chorus${only ? ` to: ${only.join(', ')}` : ''}...`);
|
|
45
|
+
console.log('');
|
|
46
|
+
try {
|
|
47
|
+
const result = await (0, index_js_1.autoConnectAll)({
|
|
48
|
+
binPath,
|
|
49
|
+
...(only && only.length > 0 ? { only } : {}),
|
|
50
|
+
});
|
|
51
|
+
const statuses = (0, index_js_1.listOrchestrators)();
|
|
52
|
+
const promptsOnce = [];
|
|
53
|
+
const inheritsGlobal = [];
|
|
54
|
+
for (const step of result.steps) {
|
|
55
|
+
if (!step.detected) {
|
|
56
|
+
console.log(` ✗ ${step.label}: not detected on this machine`);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (step.error) {
|
|
60
|
+
console.log(` ! ${step.label}: ${step.error}`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const parts = [];
|
|
64
|
+
if (step.registered)
|
|
65
|
+
parts.push('MCP server registered');
|
|
66
|
+
else
|
|
67
|
+
parts.push('MCP already registered');
|
|
68
|
+
if (step.toolsAdded > 0)
|
|
69
|
+
parts.push(`${step.toolsAdded} tool(s) approved`);
|
|
70
|
+
else if (step.name === 'claude')
|
|
71
|
+
parts.push(`all ${index_js_1.CHORUS_TOOLS.length} tools already approved`);
|
|
72
|
+
if (step.slashCommand === 'installed')
|
|
73
|
+
parts.push('/chorus command installed');
|
|
74
|
+
else if (step.slashCommand === 'updated')
|
|
75
|
+
parts.push('/chorus command updated');
|
|
76
|
+
console.log(` ✓ ${step.label}: ${parts.join(' · ')}`);
|
|
77
|
+
const status = statuses.find((s) => s.name === step.name);
|
|
78
|
+
if (status?.firstCallBehavior === 'prompts_once')
|
|
79
|
+
promptsOnce.push(step.label);
|
|
80
|
+
if (status?.firstCallBehavior === 'inherits_global')
|
|
81
|
+
inheritsGlobal.push(step.label);
|
|
82
|
+
}
|
|
83
|
+
if (!result.anyConnected) {
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log('No supported CLIs detected. Install Claude Code, Codex, Gemini, OpenCode, Kimi, Cursor, or Windsurf then retry.');
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
console.log('');
|
|
89
|
+
console.log('Restart any CLI you just connected so it picks up the new MCP server.');
|
|
90
|
+
console.log('Inside the CLI: try `/chorus bug-diagnose <paste a snippet>` (Claude) or');
|
|
91
|
+
console.log('say `chorus, run bug-diagnose on <snippet>` (any other CLI).');
|
|
92
|
+
if (promptsOnce.length > 0) {
|
|
93
|
+
console.log('');
|
|
94
|
+
console.log(`Heads up: ${promptsOnce.join(', ')} will show a one-time permission prompt`);
|
|
95
|
+
console.log('on your first chorus.* tool call. Click "Always allow" to make it stick.');
|
|
96
|
+
}
|
|
97
|
+
if (inheritsGlobal.length > 0) {
|
|
98
|
+
console.log('');
|
|
99
|
+
console.log(`${inheritsGlobal.join(', ')} use a global approval policy — whether tool calls`);
|
|
100
|
+
console.log('prompt depends on your existing config (we don\'t override it).');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
console.error(`\nFailed: ${err instanceof Error ? err.message : String(err)}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/cli/connect.ts"],"names":[],"mappings":"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"}
|