@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.
Files changed (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +437 -0
  3. package/dist/adapters/claude.js +83 -0
  4. package/dist/adapters/claude.js.map +1 -0
  5. package/dist/adapters/codex.js +382 -0
  6. package/dist/adapters/codex.js.map +1 -0
  7. package/dist/adapters/index.js +21 -0
  8. package/dist/adapters/index.js.map +1 -0
  9. package/dist/adapters/opencode.js +104 -0
  10. package/dist/adapters/opencode.js.map +1 -0
  11. package/dist/adapters/pi.js +152 -0
  12. package/dist/adapters/pi.js.map +1 -0
  13. package/dist/adapters/reasonix.js +358 -0
  14. package/dist/adapters/reasonix.js.map +1 -0
  15. package/dist/adapters/types.js +2 -0
  16. package/dist/adapters/types.js.map +1 -0
  17. package/dist/agent-markers.js +3 -0
  18. package/dist/agent-markers.js.map +1 -0
  19. package/dist/aipricing.js +109 -0
  20. package/dist/aipricing.js.map +1 -0
  21. package/dist/catalog.js +274 -0
  22. package/dist/catalog.js.map +1 -0
  23. package/dist/cli.js +766 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/commands/approve.js +23 -0
  26. package/dist/commands/approve.js.map +1 -0
  27. package/dist/commands/auth.js +41 -0
  28. package/dist/commands/auth.js.map +1 -0
  29. package/dist/commands/catalog.js +172 -0
  30. package/dist/commands/catalog.js.map +1 -0
  31. package/dist/commands/code.js +113 -0
  32. package/dist/commands/code.js.map +1 -0
  33. package/dist/commands/dispatch.js +148 -0
  34. package/dist/commands/dispatch.js.map +1 -0
  35. package/dist/commands/doctor.js +545 -0
  36. package/dist/commands/doctor.js.map +1 -0
  37. package/dist/commands/gc.js +25 -0
  38. package/dist/commands/gc.js.map +1 -0
  39. package/dist/commands/init-log.js +83 -0
  40. package/dist/commands/init-log.js.map +1 -0
  41. package/dist/commands/init.js +157 -0
  42. package/dist/commands/init.js.map +1 -0
  43. package/dist/commands/log.js +24 -0
  44. package/dist/commands/log.js.map +1 -0
  45. package/dist/commands/route.js +660 -0
  46. package/dist/commands/route.js.map +1 -0
  47. package/dist/commands/run.js +199 -0
  48. package/dist/commands/run.js.map +1 -0
  49. package/dist/commands/runs.js +37 -0
  50. package/dist/commands/runs.js.map +1 -0
  51. package/dist/commands/serve.js +818 -0
  52. package/dist/commands/serve.js.map +1 -0
  53. package/dist/commands/status.js +14 -0
  54. package/dist/commands/status.js.map +1 -0
  55. package/dist/commands/sync.js +258 -0
  56. package/dist/commands/sync.js.map +1 -0
  57. package/dist/commands/tail.js +229 -0
  58. package/dist/commands/tail.js.map +1 -0
  59. package/dist/commands/usage.js +85 -0
  60. package/dist/commands/usage.js.map +1 -0
  61. package/dist/commands/verify.js +69 -0
  62. package/dist/commands/verify.js.map +1 -0
  63. package/dist/commands/wait.js +38 -0
  64. package/dist/commands/wait.js.map +1 -0
  65. package/dist/config.js +588 -0
  66. package/dist/config.js.map +1 -0
  67. package/dist/detect.js +445 -0
  68. package/dist/detect.js.map +1 -0
  69. package/dist/filelock.js +83 -0
  70. package/dist/filelock.js.map +1 -0
  71. package/dist/init/apply.js +96 -0
  72. package/dist/init/apply.js.map +1 -0
  73. package/dist/init/candidates.js +115 -0
  74. package/dist/init/candidates.js.map +1 -0
  75. package/dist/init/discover.js +216 -0
  76. package/dist/init/discover.js.map +1 -0
  77. package/dist/init/helpers.js +429 -0
  78. package/dist/init/helpers.js.map +1 -0
  79. package/dist/init/interactive-state.js +128 -0
  80. package/dist/init/interactive-state.js.map +1 -0
  81. package/dist/init/plan.js +225 -0
  82. package/dist/init/plan.js.map +1 -0
  83. package/dist/init/scripted-state.js +130 -0
  84. package/dist/init/scripted-state.js.map +1 -0
  85. package/dist/init/toml.js +83 -0
  86. package/dist/init/toml.js.map +1 -0
  87. package/dist/init/validate.js +149 -0
  88. package/dist/init/validate.js.map +1 -0
  89. package/dist/ledger.js +123 -0
  90. package/dist/ledger.js.map +1 -0
  91. package/dist/mcp/protocol.js +64 -0
  92. package/dist/mcp/protocol.js.map +1 -0
  93. package/dist/mcp/server.js +96 -0
  94. package/dist/mcp/server.js.map +1 -0
  95. package/dist/mcp/tools.js +210 -0
  96. package/dist/mcp/tools.js.map +1 -0
  97. package/dist/mode.js +64 -0
  98. package/dist/mode.js.map +1 -0
  99. package/dist/native/claude-shim.js +228 -0
  100. package/dist/native/claude-shim.js.map +1 -0
  101. package/dist/native/codex-auth.js +177 -0
  102. package/dist/native/codex-auth.js.map +1 -0
  103. package/dist/native/copilot-auth.js +105 -0
  104. package/dist/native/copilot-auth.js.map +1 -0
  105. package/dist/native/credentials.js +83 -0
  106. package/dist/native/credentials.js.map +1 -0
  107. package/dist/native/hosts.js +60 -0
  108. package/dist/native/hosts.js.map +1 -0
  109. package/dist/native/litellm.js +103 -0
  110. package/dist/native/litellm.js.map +1 -0
  111. package/dist/native/models.js +96 -0
  112. package/dist/native/models.js.map +1 -0
  113. package/dist/native/oauth-login.js +112 -0
  114. package/dist/native/oauth-login.js.map +1 -0
  115. package/dist/native/router.js +469 -0
  116. package/dist/native/router.js.map +1 -0
  117. package/dist/native/tls.js +73 -0
  118. package/dist/native/tls.js.map +1 -0
  119. package/dist/native/usage.js +119 -0
  120. package/dist/native/usage.js.map +1 -0
  121. package/dist/normalize.js +98 -0
  122. package/dist/normalize.js.map +1 -0
  123. package/dist/pricing.js +86 -0
  124. package/dist/pricing.js.map +1 -0
  125. package/dist/roles.js +49 -0
  126. package/dist/roles.js.map +1 -0
  127. package/dist/sessions.js +62 -0
  128. package/dist/sessions.js.map +1 -0
  129. package/dist/settings.js +131 -0
  130. package/dist/settings.js.map +1 -0
  131. package/dist/store.js +70 -0
  132. package/dist/store.js.map +1 -0
  133. package/dist/tmux.js +89 -0
  134. package/dist/tmux.js.map +1 -0
  135. package/dist/tui-ink/app-state.js +340 -0
  136. package/dist/tui-ink/app-state.js.map +1 -0
  137. package/dist/tui-ink/app.js +156 -0
  138. package/dist/tui-ink/app.js.map +1 -0
  139. package/dist/tui-ink/components/byok-step.js +102 -0
  140. package/dist/tui-ink/components/byok-step.js.map +1 -0
  141. package/dist/tui-ink/components/login-screen.js +80 -0
  142. package/dist/tui-ink/components/login-screen.js.map +1 -0
  143. package/dist/tui-ink/components/models-step.js +92 -0
  144. package/dist/tui-ink/components/models-step.js.map +1 -0
  145. package/dist/tui-ink/components/multi-select-state.js +56 -0
  146. package/dist/tui-ink/components/multi-select-state.js.map +1 -0
  147. package/dist/tui-ink/components/multi-select.js +69 -0
  148. package/dist/tui-ink/components/multi-select.js.map +1 -0
  149. package/dist/tui-ink/components/providers-step.js +285 -0
  150. package/dist/tui-ink/components/providers-step.js.map +1 -0
  151. package/dist/tui-ink/components/ranked-select-state.js +41 -0
  152. package/dist/tui-ink/components/ranked-select-state.js.map +1 -0
  153. package/dist/tui-ink/components/ranked-select.js +61 -0
  154. package/dist/tui-ink/components/ranked-select.js.map +1 -0
  155. package/dist/tui-ink/components/search-select.js +47 -0
  156. package/dist/tui-ink/components/search-select.js.map +1 -0
  157. package/dist/tui-ink/components/text-input-state.js +42 -0
  158. package/dist/tui-ink/components/text-input-state.js.map +1 -0
  159. package/dist/tui-ink/components/text-input.js +48 -0
  160. package/dist/tui-ink/components/text-input.js.map +1 -0
  161. package/dist/tui-ink/run.js +38 -0
  162. package/dist/tui-ink/run.js.map +1 -0
  163. package/dist/tui-ink/test-compile.js +4 -0
  164. package/dist/tui-ink/test-compile.js.map +1 -0
  165. package/dist/tui-ink/types.js +2 -0
  166. package/dist/tui-ink/types.js.map +1 -0
  167. package/dist/tui.js +330 -0
  168. package/dist/tui.js.map +1 -0
  169. package/dist/types.js +2 -0
  170. package/dist/types.js.map +1 -0
  171. package/dist/watchdog.js +85 -0
  172. package/dist/watchdog.js.map +1 -0
  173. package/hooks/capture-mode.mjs +56 -0
  174. package/hooks/ensure-serve.mjs +140 -0
  175. package/hooks/hooks.json +12 -0
  176. package/hooks/route-session.mjs +47 -0
  177. package/hooks/route-subagent.mjs +54 -0
  178. package/package.json +64 -0
  179. package/roles/code.md +13 -0
  180. package/roles/explore.md +9 -0
  181. package/roles/plan.md +10 -0
  182. package/roles/review.md +11 -0
  183. 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"}