@zhihaohong52/sonata 0.4.0
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/LICENSE +21 -0
- package/README.md +437 -0
- package/dist/adapters/claude.js +83 -0
- package/dist/adapters/claude.js.map +1 -0
- package/dist/adapters/codex.js +382 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/index.js +21 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/adapters/opencode.js +104 -0
- package/dist/adapters/opencode.js.map +1 -0
- package/dist/adapters/pi.js +152 -0
- package/dist/adapters/pi.js.map +1 -0
- package/dist/adapters/reasonix.js +358 -0
- package/dist/adapters/reasonix.js.map +1 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/agent-markers.js +3 -0
- package/dist/agent-markers.js.map +1 -0
- package/dist/aipricing.js +109 -0
- package/dist/aipricing.js.map +1 -0
- package/dist/catalog.js +274 -0
- package/dist/catalog.js.map +1 -0
- package/dist/cli.js +766 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/approve.js +23 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/auth.js +41 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/catalog.js +172 -0
- package/dist/commands/catalog.js.map +1 -0
- package/dist/commands/code.js +113 -0
- package/dist/commands/code.js.map +1 -0
- package/dist/commands/dispatch.js +148 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/doctor.js +545 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/gc.js +25 -0
- package/dist/commands/gc.js.map +1 -0
- package/dist/commands/init-log.js +83 -0
- package/dist/commands/init-log.js.map +1 -0
- package/dist/commands/init.js +157 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/log.js +24 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/route.js +660 -0
- package/dist/commands/route.js.map +1 -0
- package/dist/commands/run.js +199 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/runs.js +37 -0
- package/dist/commands/runs.js.map +1 -0
- package/dist/commands/serve.js +818 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/status.js +14 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/sync.js +258 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/tail.js +229 -0
- package/dist/commands/tail.js.map +1 -0
- package/dist/commands/usage.js +85 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/verify.js +69 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/commands/wait.js +38 -0
- package/dist/commands/wait.js.map +1 -0
- package/dist/config.js +588 -0
- package/dist/config.js.map +1 -0
- package/dist/detect.js +445 -0
- package/dist/detect.js.map +1 -0
- package/dist/filelock.js +83 -0
- package/dist/filelock.js.map +1 -0
- package/dist/init/apply.js +96 -0
- package/dist/init/apply.js.map +1 -0
- package/dist/init/candidates.js +115 -0
- package/dist/init/candidates.js.map +1 -0
- package/dist/init/discover.js +216 -0
- package/dist/init/discover.js.map +1 -0
- package/dist/init/helpers.js +429 -0
- package/dist/init/helpers.js.map +1 -0
- package/dist/init/interactive-state.js +128 -0
- package/dist/init/interactive-state.js.map +1 -0
- package/dist/init/plan.js +225 -0
- package/dist/init/plan.js.map +1 -0
- package/dist/init/scripted-state.js +130 -0
- package/dist/init/scripted-state.js.map +1 -0
- package/dist/init/toml.js +83 -0
- package/dist/init/toml.js.map +1 -0
- package/dist/init/validate.js +149 -0
- package/dist/init/validate.js.map +1 -0
- package/dist/ledger.js +123 -0
- package/dist/ledger.js.map +1 -0
- package/dist/mcp/protocol.js +64 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/server.js +96 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools.js +210 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mode.js +64 -0
- package/dist/mode.js.map +1 -0
- package/dist/native/claude-shim.js +228 -0
- package/dist/native/claude-shim.js.map +1 -0
- package/dist/native/codex-auth.js +177 -0
- package/dist/native/codex-auth.js.map +1 -0
- package/dist/native/copilot-auth.js +105 -0
- package/dist/native/copilot-auth.js.map +1 -0
- package/dist/native/credentials.js +83 -0
- package/dist/native/credentials.js.map +1 -0
- package/dist/native/hosts.js +60 -0
- package/dist/native/hosts.js.map +1 -0
- package/dist/native/litellm.js +103 -0
- package/dist/native/litellm.js.map +1 -0
- package/dist/native/models.js +96 -0
- package/dist/native/models.js.map +1 -0
- package/dist/native/oauth-login.js +112 -0
- package/dist/native/oauth-login.js.map +1 -0
- package/dist/native/router.js +469 -0
- package/dist/native/router.js.map +1 -0
- package/dist/native/tls.js +73 -0
- package/dist/native/tls.js.map +1 -0
- package/dist/native/usage.js +119 -0
- package/dist/native/usage.js.map +1 -0
- package/dist/normalize.js +98 -0
- package/dist/normalize.js.map +1 -0
- package/dist/pricing.js +86 -0
- package/dist/pricing.js.map +1 -0
- package/dist/roles.js +49 -0
- package/dist/roles.js.map +1 -0
- package/dist/sessions.js +62 -0
- package/dist/sessions.js.map +1 -0
- package/dist/settings.js +131 -0
- package/dist/settings.js.map +1 -0
- package/dist/store.js +70 -0
- package/dist/store.js.map +1 -0
- package/dist/tmux.js +89 -0
- package/dist/tmux.js.map +1 -0
- package/dist/tui-ink/app-state.js +340 -0
- package/dist/tui-ink/app-state.js.map +1 -0
- package/dist/tui-ink/app.js +156 -0
- package/dist/tui-ink/app.js.map +1 -0
- package/dist/tui-ink/components/byok-step.js +102 -0
- package/dist/tui-ink/components/byok-step.js.map +1 -0
- package/dist/tui-ink/components/login-screen.js +80 -0
- package/dist/tui-ink/components/login-screen.js.map +1 -0
- package/dist/tui-ink/components/models-step.js +92 -0
- package/dist/tui-ink/components/models-step.js.map +1 -0
- package/dist/tui-ink/components/multi-select-state.js +56 -0
- package/dist/tui-ink/components/multi-select-state.js.map +1 -0
- package/dist/tui-ink/components/multi-select.js +69 -0
- package/dist/tui-ink/components/multi-select.js.map +1 -0
- package/dist/tui-ink/components/providers-step.js +285 -0
- package/dist/tui-ink/components/providers-step.js.map +1 -0
- package/dist/tui-ink/components/ranked-select-state.js +41 -0
- package/dist/tui-ink/components/ranked-select-state.js.map +1 -0
- package/dist/tui-ink/components/ranked-select.js +61 -0
- package/dist/tui-ink/components/ranked-select.js.map +1 -0
- package/dist/tui-ink/components/search-select.js +47 -0
- package/dist/tui-ink/components/search-select.js.map +1 -0
- package/dist/tui-ink/components/text-input-state.js +42 -0
- package/dist/tui-ink/components/text-input-state.js.map +1 -0
- package/dist/tui-ink/components/text-input.js +48 -0
- package/dist/tui-ink/components/text-input.js.map +1 -0
- package/dist/tui-ink/run.js +38 -0
- package/dist/tui-ink/run.js.map +1 -0
- package/dist/tui-ink/test-compile.js +4 -0
- package/dist/tui-ink/test-compile.js.map +1 -0
- package/dist/tui-ink/types.js +2 -0
- package/dist/tui-ink/types.js.map +1 -0
- package/dist/tui.js +330 -0
- package/dist/tui.js.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/watchdog.js +85 -0
- package/dist/watchdog.js.map +1 -0
- package/hooks/capture-mode.mjs +56 -0
- package/hooks/ensure-serve.mjs +140 -0
- package/hooks/hooks.json +12 -0
- package/hooks/route-session.mjs +47 -0
- package/hooks/route-subagent.mjs +54 -0
- package/package.json +64 -0
- package/roles/code.md +13 -0
- package/roles/explore.md +9 -0
- package/roles/plan.md +10 -0
- package/roles/review.md +11 -0
- package/skills/loop/SKILL.md +43 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { existsSync, readdirSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { loadConfig, configPath, GLOBAL_CONFIG_RELATIVE, expectedAgentNames, isOauthGatewayAuth, } from '../config.js';
|
|
5
|
+
import { staleAgents, disabledOpencodeAgents, enableOpencodeAgent, } from '../detect.js';
|
|
6
|
+
import { getAdapter } from '../adapters/index.js';
|
|
7
|
+
import { tmuxVersion } from '../tmux.js';
|
|
8
|
+
import { modeHookPresent, readSettings, settingsPath, missingAllowEntries, } from '../settings.js';
|
|
9
|
+
import { homedir } from 'node:os';
|
|
10
|
+
import { join } from 'node:path';
|
|
11
|
+
import { findLitellm } from '../native/litellm.js';
|
|
12
|
+
import { AA_CATALOG_MAX_AGE_DAYS, aaCatalogAgeDays, loadAaCatalog } from '../catalog.js';
|
|
13
|
+
import { keyReport, resolveKeyFromSource } from '../native/credentials.js';
|
|
14
|
+
import { codexAuthReport, readChatGptOAuth } from '../native/codex-auth.js';
|
|
15
|
+
import { copilotAuthReport, copilotTokenCanExchange, readCopilotToken } from '../native/copilot-auth.js';
|
|
16
|
+
import { credentialDir, credentialFileFor } from '../native/oauth-login.js';
|
|
17
|
+
import { serveHealthUrl } from './serve.js';
|
|
18
|
+
import { nativeSessionEnv } from './code.js';
|
|
19
|
+
import { routeEnv, routeSettingsFile, autoInstalled, readSessions, routeSessionsFile, diagnoseRouteAuto, isLocalhostUrl } from './route.js';
|
|
20
|
+
const run = promisify(execFile);
|
|
21
|
+
async function hasCredentialFrom(source, auth, home) {
|
|
22
|
+
if (auth === 'copilot-oauth') {
|
|
23
|
+
// A stored GitHub token is not the same as a usable one — see the
|
|
24
|
+
// matching check on the legacy (unsourced) copilot-oauth path below.
|
|
25
|
+
const token = readCopilotToken(home);
|
|
26
|
+
return token !== null && await copilotTokenCanExchange(token);
|
|
27
|
+
}
|
|
28
|
+
return readChatGptOAuth(home, source) !== null;
|
|
29
|
+
}
|
|
30
|
+
function triple(v) {
|
|
31
|
+
const m = v.replace(/^v/, '').match(/(\d+)\.(\d+)\.(\d+)/);
|
|
32
|
+
if (!m)
|
|
33
|
+
return [0, 0, 0];
|
|
34
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
35
|
+
}
|
|
36
|
+
function cmp(a, b) {
|
|
37
|
+
for (let i = 0; i < 3; i++)
|
|
38
|
+
if (a[i] !== b[i])
|
|
39
|
+
return a[i] - b[i];
|
|
40
|
+
return 0;
|
|
41
|
+
}
|
|
42
|
+
/** Supports ranges of the form ">=X.Y.Z <A.B.C". */
|
|
43
|
+
export function checkVersion(actual, range) {
|
|
44
|
+
const a = triple(actual);
|
|
45
|
+
for (const part of range.trim().split(/\s+/)) {
|
|
46
|
+
const m = part.match(/^(>=|<)(.+)$/);
|
|
47
|
+
if (!m)
|
|
48
|
+
continue;
|
|
49
|
+
const bound = triple(m[2]);
|
|
50
|
+
if (m[1] === '>=' && cmp(a, bound) < 0)
|
|
51
|
+
return false;
|
|
52
|
+
if (m[1] === '<' && cmp(a, bound) >= 0)
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
export function staleMcpRegistration(cwd, home) {
|
|
58
|
+
for (const path of [join(cwd, '.mcp.json'), join(home, '.claude.json')]) {
|
|
59
|
+
if (!existsSync(path))
|
|
60
|
+
continue;
|
|
61
|
+
try {
|
|
62
|
+
const doc = JSON.parse(readFileSync(path, 'utf8'));
|
|
63
|
+
if (doc.mcpServers !== null && typeof doc.mcpServers === 'object'
|
|
64
|
+
&& Object.hasOwn(doc.mcpServers, 'sonata')) {
|
|
65
|
+
return `${path} still registers the removed sonata server — run \`claude mcp remove sonata\``;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// A malformed user file is not evidence of a stale registration.
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Why this project's sessions are not routed, in the user's terms.
|
|
76
|
+
*
|
|
77
|
+
* Five distinct states used to print one sentence — "tier agents need a routed
|
|
78
|
+
* session — run `sonata route auto`". That is the correct instruction for the
|
|
79
|
+
* first one only. For the rest the command is still what repairs them, but
|
|
80
|
+
* saying nothing else leaves a user who has *just run it* with no next step:
|
|
81
|
+
* the hooks are installed, `route auto` reports success, and doctor keeps
|
|
82
|
+
* failing. Each branch below names the state the command is about to fix.
|
|
83
|
+
*
|
|
84
|
+
* Exported so the message is testable without standing up a doctor run.
|
|
85
|
+
*/
|
|
86
|
+
export function routingFailureDetail(input) {
|
|
87
|
+
const need = 'tier agents need a routed session';
|
|
88
|
+
const fix = 'run `sonata route auto`';
|
|
89
|
+
const current = routeEnv(input.projectSettings).ANTHROPIC_BASE_URL;
|
|
90
|
+
// Sonata owns only `http://localhost:<port>`; `route on` refuses to clobber
|
|
91
|
+
// anything else and `route off` refuses to remove it. So a corporate proxy
|
|
92
|
+
// here is not a sonata misconfiguration, and `route auto` is not the repair
|
|
93
|
+
// — it calls `planRouteOff`, which throws on exactly this URL. Recommending
|
|
94
|
+
// it would hand the user a command that fails.
|
|
95
|
+
if (current !== undefined && !isLocalhostUrl(current)) {
|
|
96
|
+
return `${need} — ANTHROPIC_BASE_URL is set to ${current}, which sonata did not write; ` +
|
|
97
|
+
'remove or update it yourself if sonata should route this project';
|
|
98
|
+
}
|
|
99
|
+
// A base URL sonata does own, but naming a port this config no longer uses.
|
|
100
|
+
// It reads as routed to anything checking presence, and 502s on every native
|
|
101
|
+
// request — so it has to be told apart from having no routing at all.
|
|
102
|
+
if (current !== undefined && input.configuredRouterUrl !== undefined && current !== input.configuredRouterUrl) {
|
|
103
|
+
return `${need} — settings route to ${current}, but this config's router is ${input.configuredRouterUrl}; ${fix}`;
|
|
104
|
+
}
|
|
105
|
+
if (input.packageRoot === undefined)
|
|
106
|
+
return `${need} — ${fix}`;
|
|
107
|
+
const project = diagnoseRouteAuto(input.projectSettings, input.packageRoot, 'project');
|
|
108
|
+
const global = diagnoseRouteAuto(input.globalSettings, input.packageRoot, 'global');
|
|
109
|
+
// Routing is installed globally and healthy — it just cannot serve *this*
|
|
110
|
+
// project, because a project with its own sonata.toml resolves a different
|
|
111
|
+
// configuration than the machine one a global hook would load.
|
|
112
|
+
if (global.kind === 'installed' && !input.projectResolvesToMachineConfig) {
|
|
113
|
+
return `${need} — routing is installed globally, but this project has its own sonata.toml, ` +
|
|
114
|
+
`so a global hook would resolve a different config; ${fix} here, without \`--global\``;
|
|
115
|
+
}
|
|
116
|
+
// Checked before `partial`: a foreign install is also missing every command
|
|
117
|
+
// this one expects, so reporting it as incomplete would be true and useless.
|
|
118
|
+
for (const diagnosis of [project, global]) {
|
|
119
|
+
if (diagnosis.kind === 'other-install') {
|
|
120
|
+
return `${need} — the installed hooks run a different sonata (${diagnosis.roots.join(', ')}), ` +
|
|
121
|
+
`not the one you are running (${input.packageRoot}); ${fix} to repoint them`;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (const diagnosis of [project, global]) {
|
|
125
|
+
if (diagnosis.kind === 'partial') {
|
|
126
|
+
const subagent = diagnosis.missing.some((event) => event.startsWith('Subagent'));
|
|
127
|
+
return `${need} — the install is missing ${diagnosis.missing.join(' and ')}` +
|
|
128
|
+
`${subagent ? ', which are the hooks that actually route' : ''}; ${fix}`;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return `${need} — ${fix}`;
|
|
132
|
+
}
|
|
133
|
+
export async function cmdDoctor(opts) {
|
|
134
|
+
const home = opts.home ?? homedir();
|
|
135
|
+
const now = opts.now ?? (() => new Date());
|
|
136
|
+
const checks = [];
|
|
137
|
+
try {
|
|
138
|
+
checks.push({ name: 'tmux', ok: true, detail: await tmuxVersion() });
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
checks.push({ name: 'tmux', ok: false, detail: 'not installed — `brew install tmux`' });
|
|
142
|
+
}
|
|
143
|
+
let config;
|
|
144
|
+
const resolved = configPath(opts.cwd, home);
|
|
145
|
+
try {
|
|
146
|
+
config = loadConfig(opts.cwd, home);
|
|
147
|
+
checks.push({
|
|
148
|
+
name: 'sonata.toml',
|
|
149
|
+
ok: true,
|
|
150
|
+
detail: `${resolved} · ${Object.keys(config.models).length} harness + ${Object.keys(config.native?.models ?? {}).length} native models`,
|
|
151
|
+
});
|
|
152
|
+
if (config.tiers === undefined && (Object.keys(config.generate.roles).length > 0 || Object.keys(config.native?.generate ?? {}).length > 0)) {
|
|
153
|
+
checks.push({
|
|
154
|
+
name: 'legacy config',
|
|
155
|
+
ok: true,
|
|
156
|
+
detail: 'config predates [tiers] — run `sonata init` to migrate',
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
checks.push({ name: 'sonata.toml', ok: false, detail: err.message });
|
|
162
|
+
return { ok: false, checks };
|
|
163
|
+
}
|
|
164
|
+
// Tier agents call the native router first. Report a blocking warning when
|
|
165
|
+
// neither persistent routing nor route-auto hooks are configured.
|
|
166
|
+
if (config.tiers !== undefined) {
|
|
167
|
+
// Rankings only matter where tiers do. Advisory, not blocking: a stale or
|
|
168
|
+
// missing catalog still produces tiers, just from superseded scores or the
|
|
169
|
+
// built-in table — the failure is silently-wrong ordering, which is
|
|
170
|
+
// exactly the kind that goes unnoticed without being named here.
|
|
171
|
+
const catalog = loadAaCatalog(home);
|
|
172
|
+
if (catalog === undefined) {
|
|
173
|
+
checks.push({
|
|
174
|
+
name: 'model rankings',
|
|
175
|
+
ok: true,
|
|
176
|
+
detail: 'no catalog — tiers ranked from built-in defaults; run `sonata catalog update`',
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
const age = aaCatalogAgeDays(catalog.fetchedAt, now());
|
|
181
|
+
const count = Object.keys(catalog.models).length;
|
|
182
|
+
checks.push(age !== undefined && age > AA_CATALOG_MAX_AGE_DAYS
|
|
183
|
+
? {
|
|
184
|
+
name: 'model rankings',
|
|
185
|
+
ok: true,
|
|
186
|
+
detail: `catalog is ${age}d old (${catalog.fetchedAt}) — run \`sonata catalog update\``,
|
|
187
|
+
}
|
|
188
|
+
: {
|
|
189
|
+
name: 'model rankings',
|
|
190
|
+
ok: true,
|
|
191
|
+
detail: `${count} models · fetched ${catalog.fetchedAt}`,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
const projectSettings = readSettings(routeSettingsFile(opts.cwd, 'project', home));
|
|
195
|
+
const globalSettings = readSettings(routeSettingsFile(opts.cwd, 'global', home));
|
|
196
|
+
// Global routing resolves the *machine* config (bd72ec4/dd9ee9b), not
|
|
197
|
+
// necessarily `config` above — that's project-first with the machine
|
|
198
|
+
// config only as a fallback, so a project with its own sonata.toml whose
|
|
199
|
+
// [native.ports].router differs from the machine's would otherwise be
|
|
200
|
+
// checked against the wrong port for the global case.
|
|
201
|
+
let globalConfig = config;
|
|
202
|
+
try {
|
|
203
|
+
const globalPath = configPath(home, home);
|
|
204
|
+
// Load the machine config directly by its own resolved path, not by
|
|
205
|
+
// treating `home` as a project cwd — `configPath(home, home)` can
|
|
206
|
+
// still resolve to a stray `~/sonata.toml` rather than
|
|
207
|
+
// `~/.config/sonata/sonata.toml` if one happens to exist, and that
|
|
208
|
+
// is not the file the global router actually runs.
|
|
209
|
+
if (globalPath === join(home, GLOBAL_CONFIG_RELATIVE)) {
|
|
210
|
+
globalConfig = loadConfig(home, home);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
catch { /* no machine config; fall through below finds nothing routed */ }
|
|
214
|
+
// Presence alone isn't enough: a base URL left over from a since-changed
|
|
215
|
+
// [native.ports].router points a session at a port nothing is listening
|
|
216
|
+
// on, which reads as routed here and 502s on every native request.
|
|
217
|
+
const routedAt = (settings, cfg, scope) => {
|
|
218
|
+
const routerUrl = cfg.native !== undefined ? `http://localhost:${cfg.native.ports.router}` : undefined;
|
|
219
|
+
return (routerUrl !== undefined && routeEnv(settings).ANTHROPIC_BASE_URL === routerUrl) ||
|
|
220
|
+
(opts.packageRoot !== undefined && autoInstalled(settings, opts.packageRoot, scope));
|
|
221
|
+
};
|
|
222
|
+
// Global routing only actually serves this project if the project's own
|
|
223
|
+
// config resolution already IS the machine config (no project-scoped
|
|
224
|
+
// sonata.toml exists) — otherwise a project with its own config needs
|
|
225
|
+
// project-scoped routing specifically; global routing there silently
|
|
226
|
+
// resolves a different, unrelated configuration.
|
|
227
|
+
const projectResolvesToMachineConfig = configPath(opts.cwd, home) === join(home, GLOBAL_CONFIG_RELATIVE);
|
|
228
|
+
const routed = routedAt(projectSettings, config, 'project') ||
|
|
229
|
+
(projectResolvesToMachineConfig && routedAt(globalSettings, globalConfig, 'global'));
|
|
230
|
+
if (!routed) {
|
|
231
|
+
checks.push({
|
|
232
|
+
name: 'tier routing',
|
|
233
|
+
ok: false,
|
|
234
|
+
detail: routingFailureDetail({
|
|
235
|
+
cwd: opts.cwd,
|
|
236
|
+
packageRoot: opts.packageRoot,
|
|
237
|
+
projectSettings,
|
|
238
|
+
globalSettings,
|
|
239
|
+
configuredRouterUrl: config.native !== undefined
|
|
240
|
+
? `http://localhost:${config.native.ports.router}`
|
|
241
|
+
: undefined,
|
|
242
|
+
projectResolvesToMachineConfig,
|
|
243
|
+
}),
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
// `sonata init` run in $HOME used to write here, and nothing reads it. It
|
|
248
|
+
// looks exactly like configuration, which is worse than not existing.
|
|
249
|
+
const stray = join(home, 'sonata.toml');
|
|
250
|
+
if (existsSync(stray) && resolved !== stray) {
|
|
251
|
+
checks.push({
|
|
252
|
+
name: 'stray config',
|
|
253
|
+
ok: false,
|
|
254
|
+
detail: `${stray} is not read by sonata — mv it to ${join(home, GLOBAL_CONFIG_RELATIVE)}`,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
const agentsDir = join(opts.cwd, '.claude', 'agents');
|
|
258
|
+
// Shared with `sync`, which writes these files. Computing the set separately
|
|
259
|
+
// made sync write a native model's wrapper that doctor then called stale.
|
|
260
|
+
const expected = expectedAgentNames(config);
|
|
261
|
+
const stale = staleAgents(agentsDir, expected);
|
|
262
|
+
checks.push(stale.length === 0
|
|
263
|
+
? { name: 'agents', ok: true, detail: `${expected.length} generated, none stale` }
|
|
264
|
+
: {
|
|
265
|
+
name: 'agents',
|
|
266
|
+
ok: false,
|
|
267
|
+
detail: `${stale.length} stale agent file(s) name models the config does not ` +
|
|
268
|
+
`define — run \`sonata sync\` to remove them: ${stale.slice(0, 3).join(', ')}` +
|
|
269
|
+
(stale.length > 3 ? ', …' : ''),
|
|
270
|
+
});
|
|
271
|
+
if (config.native) {
|
|
272
|
+
const litellm = findLitellm();
|
|
273
|
+
checks.push(litellm
|
|
274
|
+
? { name: 'litellm', ok: true, detail: litellm }
|
|
275
|
+
: { name: 'litellm', ok: false, detail: "not found — pip install 'litellm[proxy]'" });
|
|
276
|
+
try {
|
|
277
|
+
const response = await fetch(serveHealthUrl(config.native.ports.router));
|
|
278
|
+
let body;
|
|
279
|
+
try {
|
|
280
|
+
body = await response.json();
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
body = undefined;
|
|
284
|
+
}
|
|
285
|
+
const healthy = response.status === 200
|
|
286
|
+
&& body !== null
|
|
287
|
+
&& typeof body === 'object'
|
|
288
|
+
&& body.sonata === true;
|
|
289
|
+
checks.push(healthy
|
|
290
|
+
? { name: 'serve health', ok: true, detail: 'up' }
|
|
291
|
+
: { name: 'serve health', ok: true, detail: 'not running — start with `sonata serve`' });
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// `serve` is user-started, so an unavailable endpoint is advisory.
|
|
295
|
+
checks.push({ name: 'serve health', ok: true, detail: 'not running — start with `sonata serve`' });
|
|
296
|
+
}
|
|
297
|
+
// A project can route every plain `claude` session through the router via
|
|
298
|
+
// `.claude/settings.local.json` (`sonata route on`). The env must match
|
|
299
|
+
// `nativeSessionEnv` exactly or the session silently uses a different
|
|
300
|
+
// port than the router this config names; the hook keeps the router up the
|
|
301
|
+
// way `sonata code` does.
|
|
302
|
+
{
|
|
303
|
+
const settings = readSettings(routeSettingsFile(opts.cwd));
|
|
304
|
+
const target = nativeSessionEnv(config);
|
|
305
|
+
const expectedBase = target.ANTHROPIC_BASE_URL;
|
|
306
|
+
const actualBase = routeEnv(settings).ANTHROPIC_BASE_URL;
|
|
307
|
+
if (actualBase !== undefined && actualBase !== expectedBase) {
|
|
308
|
+
checks.push({
|
|
309
|
+
name: 'routed sessions',
|
|
310
|
+
ok: false,
|
|
311
|
+
detail: `.claude/settings.local.json routes claude to ${actualBase} but ` +
|
|
312
|
+
`this config's router is ${expectedBase} — run \`sonata route on\``,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
else if (actualBase !== undefined) {
|
|
316
|
+
checks.push({
|
|
317
|
+
name: 'routed sessions',
|
|
318
|
+
ok: true,
|
|
319
|
+
detail: `claude sessions route through ${actualBase} (sonata route on)`,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// Auto mode is reported separately because it explains an otherwise
|
|
323
|
+
// confusing pair of observations: a settings file with no routing env in
|
|
324
|
+
// it, and sessions that route anyway. It also explains the reverse — a
|
|
325
|
+
// file left routed by a session that died before its SessionEnd hook.
|
|
326
|
+
if (opts.packageRoot !== undefined && autoInstalled(settings, opts.packageRoot)) {
|
|
327
|
+
const live = readSessions(routeSessionsFile(opts.cwd)).length;
|
|
328
|
+
checks.push({
|
|
329
|
+
name: 'route auto',
|
|
330
|
+
ok: true,
|
|
331
|
+
detail: live === 0
|
|
332
|
+
? 'routing follows foreign-model subagents; no sessions live now'
|
|
333
|
+
: `${live} session(s) live; routing turns on only while a subagent runs`,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
// An OAuth gateway holds no key at all — its credential is a harness login
|
|
338
|
+
// that LiteLLM reads and refreshes. Reporting it through keyReport would
|
|
339
|
+
// tell the user to `sonata auth add` a key that would be ignored, and claim
|
|
340
|
+
// no usable credential exists when one does.
|
|
341
|
+
const gatewayNames = Object.keys(config.native.gateways);
|
|
342
|
+
// A gateway with a recorded source gets exactly one check, right here — the
|
|
343
|
+
// legacy automatic-sniffing checks below are skipped for it. Running both
|
|
344
|
+
// meant a valid `credential_source = "sonata"` could pass its own check and
|
|
345
|
+
// then fail the legacy codex/opencode sniff, making `doctor` exit 1 for a
|
|
346
|
+
// correctly configured gateway.
|
|
347
|
+
const sourcedGateways = new Set(gatewayNames.filter((name) => config.native.gateways[name].credentialSource !== undefined));
|
|
348
|
+
for (const [name, gateway] of Object.entries(config.native.gateways)) {
|
|
349
|
+
const source = gateway.credentialSource;
|
|
350
|
+
if (source === undefined) {
|
|
351
|
+
// Distinct name from the `key source: <gateway>` checks below — this is
|
|
352
|
+
// informational only, and the automatic-resolution checks further down
|
|
353
|
+
// still own verifying that gateway's credential.
|
|
354
|
+
checks.push({
|
|
355
|
+
name: `credential source: ${name}`,
|
|
356
|
+
ok: true,
|
|
357
|
+
detail: `${name}: credential resolved automatically (no credential_source recorded)`,
|
|
358
|
+
});
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
const present = gateway.auth === 'api-key'
|
|
362
|
+
? (source === 'sonata' || source === 'opencode') && resolveKeyFromSource(name, home, source) !== undefined
|
|
363
|
+
: source === 'sonata'
|
|
364
|
+
? existsSync(join(credentialDir(home, name), credentialFileFor(gateway.auth)))
|
|
365
|
+
: await hasCredentialFrom(source, gateway.auth, home);
|
|
366
|
+
// The fix differs by what the source actually stores: a device-login
|
|
367
|
+
// credential is repaired with `sonata auth login`, but a bearer key is
|
|
368
|
+
// repaired with `sonata auth add` — or, for an opencode-sourced key,
|
|
369
|
+
// by logging into opencode itself, which sonata does not manage.
|
|
370
|
+
const repairHint = gateway.auth === 'api-key'
|
|
371
|
+
? source === 'sonata'
|
|
372
|
+
? `run \`sonata auth add ${name}\``
|
|
373
|
+
: `log into opencode itself — sonata does not manage opencode credentials`
|
|
374
|
+
: source === 'sonata'
|
|
375
|
+
? `run \`sonata auth login ${name}\``
|
|
376
|
+
: source === 'codex'
|
|
377
|
+
? 'log in with `codex login`'
|
|
378
|
+
: gateway.auth === 'copilot-oauth'
|
|
379
|
+
? 'log into opencode with a GitHub Copilot account'
|
|
380
|
+
: 'log into opencode with a ChatGPT account';
|
|
381
|
+
checks.push({
|
|
382
|
+
name: `key source: ${name}`,
|
|
383
|
+
ok: present,
|
|
384
|
+
detail: present
|
|
385
|
+
? `${name}: credential from ${source}`
|
|
386
|
+
: `${name}: credential from ${source}\n ! ${name}: no credential from ${source} — ${repairHint}`,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
const oauthGateways = gatewayNames.filter((name) => isOauthGatewayAuth(config.native.gateways[name].auth) && !sourcedGateways.has(name));
|
|
390
|
+
for (const gateway of oauthGateways) {
|
|
391
|
+
if (config.native.gateways[gateway].auth === 'copilot-oauth') {
|
|
392
|
+
const report = copilotAuthReport(home);
|
|
393
|
+
if (report.problem !== undefined) {
|
|
394
|
+
checks.push({ name: `key source: ${gateway}`, ok: false, detail: report.problem });
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
// Having a token is not the same as being able to use it: opencode
|
|
398
|
+
// requests only `read:user`, and GitHub then refuses the Copilot
|
|
399
|
+
// exchange with a 403 that LiteLLM turns into "no healthy deployments".
|
|
400
|
+
const token = readCopilotToken(home);
|
|
401
|
+
const usable = token !== null && await copilotTokenCanExchange(token);
|
|
402
|
+
checks.push(usable
|
|
403
|
+
? { name: `key source: ${gateway}`, ok: true, detail: 'GitHub Copilot login from opencode' }
|
|
404
|
+
: {
|
|
405
|
+
name: `key source: ${gateway}`,
|
|
406
|
+
ok: false,
|
|
407
|
+
detail: 'the stored GitHub token cannot mint a Copilot key — it needs the ' +
|
|
408
|
+
'`copilot` scope (opencode requests only read:user)',
|
|
409
|
+
});
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const report = codexAuthReport(home);
|
|
413
|
+
checks.push({
|
|
414
|
+
name: `key source: ${gateway}`,
|
|
415
|
+
ok: report.problem === undefined,
|
|
416
|
+
detail: report.problem
|
|
417
|
+
?? `ChatGPT subscription from ${report.source ?? 'codex'}` +
|
|
418
|
+
(report.expired ? ' (expired, refreshes on use)' : ''),
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
const keyGateways = gatewayNames.filter((name) => !oauthGateways.includes(name) && !sourcedGateways.has(name));
|
|
422
|
+
for (const report of keyReport(keyGateways, home)) {
|
|
423
|
+
checks.push(report.source
|
|
424
|
+
? { name: `key source: ${report.gateway}`, ok: true, detail: `from ${report.source}` }
|
|
425
|
+
: {
|
|
426
|
+
name: `key source: ${report.gateway}`,
|
|
427
|
+
ok: false,
|
|
428
|
+
detail: `no key — \`sonata auth add ${report.gateway}\``,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
const wrappers = existsSync(agentsDir)
|
|
433
|
+
? readdirSync(agentsDir).filter((f) => f.endsWith('.md')).filter((f) => readFileSync(join(agentsDir, f), 'utf8')
|
|
434
|
+
.includes('forwarding wrapper around the sonata runtime'))
|
|
435
|
+
: [];
|
|
436
|
+
const withBash = wrappers.filter((f) => /^tools:\s*Bash\s*$/m.test(readFileSync(join(agentsDir, f), 'utf8')));
|
|
437
|
+
// Catches both generations of removed MCP tool names: run/tail (pre-dispatch
|
|
438
|
+
// rename) and dispatch/wait/approve (the MCP server itself, removed when the
|
|
439
|
+
// Bash CLI replaced it) — an upgrade from either still has wrappers naming
|
|
440
|
+
// tools that no longer exist.
|
|
441
|
+
const stalePolling = wrappers.filter((f) => /mcp__[^_\s]+__(run|tail|dispatch|wait|approve)\b/.test(readFileSync(join(agentsDir, f), 'utf8')));
|
|
442
|
+
checks.push(stalePolling.length === 0
|
|
443
|
+
? { name: 'agent tools', ok: withBash.length === 0, detail: withBash.length === 0
|
|
444
|
+
? 'no wrapper grants Bash'
|
|
445
|
+
: `${withBash.length} wrapper(s) still grant Bash and can do the work ` +
|
|
446
|
+
'themselves — run `sonata sync`' }
|
|
447
|
+
: {
|
|
448
|
+
name: 'agent tools',
|
|
449
|
+
ok: false,
|
|
450
|
+
detail: `${stalePolling.length} wrapper(s) still call removed MCP ` +
|
|
451
|
+
'tools and will fail mid-dispatch — run `sonata sync`',
|
|
452
|
+
});
|
|
453
|
+
// Agents sonata dispatches to. A disabled one is not an error opencode
|
|
454
|
+
// reports: `--agent explore` falls back to the write-capable `build` with a
|
|
455
|
+
// warning in the pane that nothing parses, so a read-only role silently
|
|
456
|
+
// stops being read-only. Corrected rather than reported, because the
|
|
457
|
+
// failure is invisible and the fix is one field.
|
|
458
|
+
const NEEDED_OPENCODE_AGENTS = ['explore', 'plan', 'build'];
|
|
459
|
+
const disabled = disabledOpencodeAgents(home).filter((a) => NEEDED_OPENCODE_AGENTS.includes(a));
|
|
460
|
+
if (disabled.length === 0) {
|
|
461
|
+
checks.push({ name: 'opencode agents', ok: true, detail: 'none sonata needs are disabled' });
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
const fixed = disabled.filter((a) => enableOpencodeAgent(home, a));
|
|
465
|
+
checks.push({
|
|
466
|
+
name: 'opencode agents',
|
|
467
|
+
ok: fixed.length === disabled.length,
|
|
468
|
+
detail: fixed.length > 0
|
|
469
|
+
? `re-enabled ${fixed.join(', ')} in opencode.json — disabled, a read-only role ` +
|
|
470
|
+
'silently runs under the write-capable `build`'
|
|
471
|
+
: `${disabled.join(', ')} disabled in opencode.json and could not be re-enabled`,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
const staleMcp = staleMcpRegistration(opts.cwd, home);
|
|
475
|
+
if (staleMcp !== undefined) {
|
|
476
|
+
checks.push({ name: 'stale MCP registration', ok: false, detail: staleMcp });
|
|
477
|
+
}
|
|
478
|
+
const harnesses = new Set(Object.values(config.models).map((m) => m.harness));
|
|
479
|
+
// Without the hook sonata cannot read the session's permission mode and
|
|
480
|
+
// assumes `default` — which a harness that cannot ask for approval refuses
|
|
481
|
+
// outright, so every dispatch to it fails. Say that here rather than letting
|
|
482
|
+
// it surface as a confusing failure on first use.
|
|
483
|
+
const cannotAsk = [...harnesses].filter((h) => !getAdapter(h).canPromptForApproval);
|
|
484
|
+
if (cannotAsk.length > 0) {
|
|
485
|
+
const installed = ['project', 'global'].some((scope) => modeHookPresent(readSettings(settingsPath(scope, opts.cwd, homedir()))));
|
|
486
|
+
checks.push({
|
|
487
|
+
name: 'permission hook',
|
|
488
|
+
ok: installed,
|
|
489
|
+
detail: installed
|
|
490
|
+
? 'installed — the session permission mode is visible to sonata'
|
|
491
|
+
: `not installed, so sonata assumes \`default\`, which ${cannotAsk.join(' and ')} ` +
|
|
492
|
+
'cannot honour — those dispatches will refuse. Run `sonata init`',
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
// The wrapper's three tools must be allow-listed. Left to `auto` mode they
|
|
496
|
+
// are judged per call and the decisions are not stable: a wrapper on
|
|
497
|
+
// 2026-08-12 had `tail` allowed twice then denied twice mid-run, so the run
|
|
498
|
+
// kept going with nothing able to read it back. `run` executes code, and it
|
|
499
|
+
// is the one the classifier tends to permit — so the failure is silent by
|
|
500
|
+
// construction, and worth naming before it happens rather than after.
|
|
501
|
+
{
|
|
502
|
+
const scopes = ['project', 'global'];
|
|
503
|
+
const missing = scopes
|
|
504
|
+
.map((scope) => missingAllowEntries(readSettings(settingsPath(scope, opts.cwd, homedir()))))
|
|
505
|
+
.reduce((a, b) => (a.length <= b.length ? a : b));
|
|
506
|
+
checks.push({
|
|
507
|
+
name: 'tool permissions',
|
|
508
|
+
ok: missing.length === 0,
|
|
509
|
+
detail: missing.length === 0
|
|
510
|
+
? 'the sonata tools are allow-listed, so no dispatch depends on the classifier'
|
|
511
|
+
: `${missing.join(', ')} not allow-listed — in \`auto\` mode these are judged per call, ` +
|
|
512
|
+
'and a denied `wait` leaves a paused dispatch unobservable. Run `sonata init`',
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
for (const name of harnesses) {
|
|
516
|
+
const adapter = getAdapter(name);
|
|
517
|
+
try {
|
|
518
|
+
const env = { ...process.env, PATH: `${process.env.HOME}/.opencode/bin:${process.env.PATH}` };
|
|
519
|
+
const { stdout } = await run(adapter.versionCommand[0], adapter.versionCommand.slice(1), { env });
|
|
520
|
+
const version = stdout.trim();
|
|
521
|
+
const ok = checkVersion(version, adapter.supportedVersions);
|
|
522
|
+
checks.push({
|
|
523
|
+
name,
|
|
524
|
+
ok,
|
|
525
|
+
detail: ok ? version : `${version} outside tested range ${adapter.supportedVersions}`,
|
|
526
|
+
});
|
|
527
|
+
// Version alone does not mean usable: a harness can be installed, current
|
|
528
|
+
// and still unable to reach a model.
|
|
529
|
+
if (adapter.health) {
|
|
530
|
+
for (const p of await adapter.health({ home: homedir(), cwd: opts.cwd })) {
|
|
531
|
+
checks.push({
|
|
532
|
+
name: `${name} health`,
|
|
533
|
+
ok: p.severity !== 'error',
|
|
534
|
+
detail: p.fix ? `${p.message} — ${p.fix}` : p.message,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
checks.push({ name, ok: false, detail: 'not found on PATH' });
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return { ok: checks.every((c) => c.ok), checks };
|
|
544
|
+
}
|
|
545
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/commands/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { listSessions, killSession, currentSession } from '../tmux.js';
|
|
2
|
+
import { listRuns, readExit } from '../store.js';
|
|
3
|
+
/**
|
|
4
|
+
* Kills tmux sessions whose run has finished. Live runs are never touched, and
|
|
5
|
+
* neither is the session gc is itself running inside — an agent that manages
|
|
6
|
+
* tmux can otherwise kill the pane it lives in, losing its own exit sentinel.
|
|
7
|
+
*/
|
|
8
|
+
export async function cmdGc(opts) {
|
|
9
|
+
const sessions = await listSessions();
|
|
10
|
+
const self = await currentSession();
|
|
11
|
+
const killed = [];
|
|
12
|
+
for (const id of listRuns(opts.cwd)) {
|
|
13
|
+
const session = `sonata-${id}`;
|
|
14
|
+
if (!sessions.includes(session))
|
|
15
|
+
continue;
|
|
16
|
+
if (session === self)
|
|
17
|
+
continue;
|
|
18
|
+
if (readExit(opts.cwd, id) === null)
|
|
19
|
+
continue;
|
|
20
|
+
await killSession(session);
|
|
21
|
+
killed.push(session);
|
|
22
|
+
}
|
|
23
|
+
return killed;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=gc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gc.js","sourceRoot":"","sources":["../../src/commands/gc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,KAAK,CAAC,IAAqB;IAC/C,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,cAAc,EAAE,CAAC;IACpC,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,KAAK,MAAM,EAAE,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,UAAU,EAAE,EAAE,CAAC;QAC/B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAS;QAC1C,IAAI,OAAO,KAAK,IAAI;YAAE,SAAS;QAC/B,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,IAAI;YAAE,SAAS;QAC9C,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|