@spinabot/brigade 1.23.0 → 1.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agents/agent-loop.d.ts.map +1 -1
- package/dist/agents/agent-loop.js +73 -3
- package/dist/agents/agent-loop.js.map +1 -1
- package/dist/agents/channels/inbound-pipeline.d.ts.map +1 -1
- package/dist/agents/channels/inbound-pipeline.js +6 -0
- package/dist/agents/channels/inbound-pipeline.js.map +1 -1
- package/dist/agents/claude-cli/availability.d.ts +12 -0
- package/dist/agents/claude-cli/availability.d.ts.map +1 -0
- package/dist/agents/claude-cli/availability.js +79 -0
- package/dist/agents/claude-cli/availability.js.map +1 -0
- package/dist/agents/claude-cli/catalog.d.ts +91 -0
- package/dist/agents/claude-cli/catalog.d.ts.map +1 -0
- package/dist/agents/claude-cli/catalog.js +260 -0
- package/dist/agents/claude-cli/catalog.js.map +1 -0
- package/dist/agents/claude-cli/claude-config.d.ts +38 -0
- package/dist/agents/claude-cli/claude-config.d.ts.map +1 -0
- package/dist/agents/claude-cli/claude-config.js +111 -0
- package/dist/agents/claude-cli/claude-config.js.map +1 -0
- package/dist/agents/claude-cli/register.d.ts +32 -0
- package/dist/agents/claude-cli/register.d.ts.map +1 -0
- package/dist/agents/claude-cli/register.js +68 -0
- package/dist/agents/claude-cli/register.js.map +1 -0
- package/dist/agents/claude-cli/spawn.d.ts +42 -0
- package/dist/agents/claude-cli/spawn.d.ts.map +1 -0
- package/dist/agents/claude-cli/spawn.js +179 -0
- package/dist/agents/claude-cli/spawn.js.map +1 -0
- package/dist/agents/claude-cli/stream-json.d.ts +129 -0
- package/dist/agents/claude-cli/stream-json.d.ts.map +1 -0
- package/dist/agents/claude-cli/stream-json.js +84 -0
- package/dist/agents/claude-cli/stream-json.js.map +1 -0
- package/dist/agents/claude-cli/stream.d.ts +27 -0
- package/dist/agents/claude-cli/stream.d.ts.map +1 -0
- package/dist/agents/claude-cli/stream.js +380 -0
- package/dist/agents/claude-cli/stream.js.map +1 -0
- package/dist/agents/error-classifier.d.ts +2 -2
- package/dist/agents/error-classifier.d.ts.map +1 -1
- package/dist/agents/error-classifier.js +43 -0
- package/dist/agents/error-classifier.js.map +1 -1
- package/dist/agents/model-resolution.d.ts +36 -0
- package/dist/agents/model-resolution.d.ts.map +1 -1
- package/dist/agents/model-resolution.js +59 -0
- package/dist/agents/model-resolution.js.map +1 -1
- package/dist/agents/retry-policy.d.ts.map +1 -1
- package/dist/agents/retry-policy.js +25 -1
- package/dist/agents/retry-policy.js.map +1 -1
- package/dist/auth/auth-health.d.ts +89 -0
- package/dist/auth/auth-health.d.ts.map +1 -1
- package/dist/auth/auth-health.js +207 -1
- package/dist/auth/auth-health.js.map +1 -1
- package/dist/buildstamp.json +1 -1
- package/dist/cli/commands/auth.js +18 -0
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +46 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/gateway.d.ts +4 -0
- package/dist/cli/commands/gateway.d.ts.map +1 -1
- package/dist/cli/commands/gateway.js +44 -2
- package/dist/cli/commands/gateway.js.map +1 -1
- package/dist/cli/commands/login.d.ts.map +1 -1
- package/dist/cli/commands/login.js +107 -19
- package/dist/cli/commands/login.js.map +1 -1
- package/dist/core/auth-bridge.d.ts.map +1 -1
- package/dist/core/auth-bridge.js +16 -0
- package/dist/core/auth-bridge.js.map +1 -1
- package/dist/core/server.d.ts.map +1 -1
- package/dist/core/server.js +13 -0
- package/dist/core/server.js.map +1 -1
- package/dist/providers/catalog.d.ts.map +1 -1
- package/dist/providers/catalog.js +18 -0
- package/dist/providers/catalog.js.map +1 -1
- package/dist/ui/onboarding.d.ts +11 -0
- package/dist/ui/onboarding.d.ts.map +1 -1
- package/dist/ui/onboarding.js +343 -4
- package/dist/ui/onboarding.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/providers/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,YAAY;IAC5B,iGAAiG;IACjG,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oGAAoG;IACpG,YAAY,CAAC,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D;;;;;OAKG;IACH,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD;;;;;OAKG;IACH,GAAG,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,CAAC;IAClD,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,SAAS,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/providers/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,YAAY;IAC5B,iGAAiG;IACjG,EAAE,EAAE,MAAM,CAAC;IACX;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,CAAC;IACf,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,oGAAoG;IACpG,YAAY,CAAC,EAAE;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1D;;;;;OAKG;IACH,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD;;;;;OAKG;IACH,GAAG,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,CAAC;IAClD,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,SAAS,EAAE,YAAY,EA0MnC,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS,CAEjE;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,CAAC,EAAE,YAAY,GAAG,SAAS,GAAG,CAAC,IAAI,YAAY,GAAG;IAAE,MAAM,EAAE,IAAI,CAAA;CAAE,CAExG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,GAAG,SAAS,CAE7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAC1C,QAAQ,EAAE,YAAY,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAW7C"}
|
|
@@ -37,6 +37,24 @@ export const PROVIDERS = [
|
|
|
37
37
|
subscription: { oauthProviderId: "anthropic", label: "Log in with Claude Pro / Max" },
|
|
38
38
|
cliLogin: { read: "claude", label: "Use your existing Claude Code login" },
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
// The claude-cli backend: Brigade drives the installed `claude` binary as
|
|
42
|
+
// the inference transport, so a turn bills against the Claude subscription
|
|
43
|
+
// EXACTLY like the Claude Code CLI / IDE extension (the binary uses its own
|
|
44
|
+
// login; Anthropic never routes it into the metered "extra usage" tier the
|
|
45
|
+
// raw-HTTP OAuth path can hit). No key + no browser flow here — the binary
|
|
46
|
+
// authenticates itself; if it isn't logged in, the operator runs
|
|
47
|
+
// `claude` once (or `claude /login`). `local:true` makes onboarding skip
|
|
48
|
+
// key entry and validate the binary instead; models are synthesized (see
|
|
49
|
+
// src/agents/claude-cli), so there's no catalog/models.json entry to seed.
|
|
50
|
+
id: "claude-cli",
|
|
51
|
+
name: "Claude (via Claude Code CLI)",
|
|
52
|
+
description: "Run on your Claude subscription through the installed claude binary — no key, no extra-usage",
|
|
53
|
+
keyUrl: "https://claude.ai/download",
|
|
54
|
+
envVar: "",
|
|
55
|
+
noAuth: true,
|
|
56
|
+
local: true,
|
|
57
|
+
},
|
|
40
58
|
{
|
|
41
59
|
id: "openai",
|
|
42
60
|
name: "OpenAI",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/providers/catalog.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/providers/catalog.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/onboarding.d.ts
CHANGED
|
@@ -98,6 +98,17 @@ export declare function ensureApiKey(tui: TUI, authStorage: AuthStorage, provide
|
|
|
98
98
|
* provider.
|
|
99
99
|
*/
|
|
100
100
|
export declare function ensureSubscriptionLogin(tui: TUI, authStorage: AuthStorage, provider: ProviderInfo): Promise<"ok" | "back">;
|
|
101
|
+
/**
|
|
102
|
+
* Connect the claude-cli backend end to end — no terminal, no token paste:
|
|
103
|
+
* 1. Ensure the `claude` binary is installed (offer to `npm i -g` it).
|
|
104
|
+
* 2. Ensure a login exists — if not, drive the SAME browser OAuth Brigade uses
|
|
105
|
+
* for Claude Pro/Max and write the result into Brigade's OWN Claude config
|
|
106
|
+
* dir (a dedicated grant, isolated from the operator's personal ~/.claude).
|
|
107
|
+
* Turns then run on the Claude subscription via the binary (no extra-usage).
|
|
108
|
+
*
|
|
109
|
+
* Returns "ok" to proceed to model selection, or "back" to re-pick the provider.
|
|
110
|
+
*/
|
|
111
|
+
export declare function ensureClaudeCli(tui: TUI, authStorage: AuthStorage): Promise<"ok" | "back">;
|
|
101
112
|
/**
|
|
102
113
|
* Render an API key in a form safe to splat to the terminal/log: shows the
|
|
103
114
|
* first 4 and last 4 characters separated by an ellipsis, e.g. `sk-o…2b5x`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/ui/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAA+D,GAAG,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../../src/ui/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAClF,OAAO,EAA+D,GAAG,EAAE,MAAM,wBAAwB,CAAC;AAgB1G,OAAO,EAMN,KAAK,YAAY,EACjB,MAAM,yBAAyB,CAAC;AAIjC,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAWpF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB;+DAC2D;IAC3D,OAAO,EAAE,iBAAiB,CAAC;CAC3B;AAiGD,MAAM,WAAW,iBAAiB;IACjC;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IACtC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAsB,aAAa,CAClC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,WAAW,EACxB,aAAa,EAAE,aAAa,EAC5B,IAAI,GAAE,iBAAsB,GAC1B,OAAO,CAAC,gBAAgB,CAAC,CA4P3B;AAuHD;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CACjC,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,WAAW,GAAG,KAAK,CAAA;CAAO,GACzE,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAoLxB;AAkND;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC5C,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CA+MxB;AAQD;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CA4GhG;AA+lBD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CASpG"}
|
package/dist/ui/onboarding.js
CHANGED
|
@@ -25,6 +25,9 @@ import { upsertApiKeyProfile, upsertApiKeyRefProfile, upsertOAuthProfile, upsert
|
|
|
25
25
|
import { DEFAULT_AGENT_ID, resolveAuthProfilesPath, resolveModelsPath } from "../config/paths.js";
|
|
26
26
|
import { saveConfig } from "../core/config.js";
|
|
27
27
|
import { readClaudeCliLogin, readCodexCliLogin } from "../integrations/cli-login.js";
|
|
28
|
+
import { isClaudeCliAvailable } from "../agents/claude-cli/availability.js";
|
|
29
|
+
import { CLAUDE_CLI_DEFAULT_MODEL, CLAUDE_CLI_MODELS } from "../agents/claude-cli/catalog.js";
|
|
30
|
+
import { hasBrigadeClaudeLogin, writeBrigadeClaudeCredential } from "../agents/claude-cli/claude-config.js";
|
|
28
31
|
import { writeCustomProviderToModelsJson } from "../integrations/custom-provider.js";
|
|
29
32
|
import { discoverOllamaModels, writeOllamaToModelsJson } from "../integrations/ollama.js";
|
|
30
33
|
import { findProvider, PROVIDERS, readProviderEnvKey, resolveProviderEnvVarSource, routesToCustomProvider, } from "../providers/catalog.js";
|
|
@@ -194,6 +197,19 @@ export async function runOnboarding(tui, authStorage, modelRegistry, opts = {})
|
|
|
194
197
|
step = "model";
|
|
195
198
|
continue;
|
|
196
199
|
}
|
|
200
|
+
// claude-cli backend — no key + no browser flow: the `claude` binary
|
|
201
|
+
// authenticates with its OWN login. Validate the binary is installed
|
|
202
|
+
// and logged in; if not, guide the operator to run `claude` once. Models
|
|
203
|
+
// are synthesized, so nothing is written to models.json.
|
|
204
|
+
if (providerInfo?.id === "claude-cli") {
|
|
205
|
+
const result = await ensureClaudeCli(tui, authStorage);
|
|
206
|
+
if (result === "back") {
|
|
207
|
+
step = "provider";
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
step = "model";
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
197
213
|
// CLI-login reuse — if the provider can adopt an already-logged-in
|
|
198
214
|
// vendor CLI's token on this machine (Claude Code, Codex), offer the
|
|
199
215
|
// one-keystroke "reuse this login" path FIRST. "other" means no CLI
|
|
@@ -261,6 +277,17 @@ export async function runOnboarding(tui, authStorage, modelRegistry, opts = {})
|
|
|
261
277
|
}
|
|
262
278
|
// step === "model"
|
|
263
279
|
renderScreen(tui, "Step 4 of 5 · Default model");
|
|
280
|
+
// claude-cli models are synthesized (not in the registry), so pick from the
|
|
281
|
+
// backend's own catalog instead of the registry-backed picker.
|
|
282
|
+
if (provider === "claude-cli") {
|
|
283
|
+
const result = await pickClaudeCliModel(tui);
|
|
284
|
+
if (result === "back") {
|
|
285
|
+
step = "provider";
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
288
|
+
modelId = result.modelId;
|
|
289
|
+
break; // model chosen — exit the wizard loop to persist + finish
|
|
290
|
+
}
|
|
264
291
|
const result = await pickModel(tui, modelRegistry, findProvider(provider)?.providerId ?? provider);
|
|
265
292
|
if (result === "back") {
|
|
266
293
|
step = "provider"; // go all the way back so they can change provider too
|
|
@@ -383,10 +410,22 @@ async function pickProvider(tui) {
|
|
|
383
410
|
const isBYO = p.custom === true && !p.baseUrl;
|
|
384
411
|
let rank;
|
|
385
412
|
let badge;
|
|
386
|
-
//
|
|
387
|
-
//
|
|
388
|
-
//
|
|
389
|
-
|
|
413
|
+
// The claude-cli backend: it's `local+noAuth` in the catalog, but it's a
|
|
414
|
+
// SUBSCRIPTION path, not a local server. Rank it with the subscription tier
|
|
415
|
+
// and surface it at the very top when the binary is installed + logged in
|
|
416
|
+
// (the cleanest "no extra-usage" route). Checked BEFORE the generic
|
|
417
|
+
// cliReady / local branches so it doesn't get the wrong badge.
|
|
418
|
+
if (p.id === "claude-cli") {
|
|
419
|
+
const ready = isClaudeCliAvailable() && (readClaudeCliLogin() !== null || hasBrigadeClaudeLogin());
|
|
420
|
+
rank = ready ? 0 : 2;
|
|
421
|
+
badge = ready
|
|
422
|
+
? "installed + signed in — subscription, no key, no extra-usage"
|
|
423
|
+
: "your Claude subscription — browser sign-in, no key, no extra-usage";
|
|
424
|
+
}
|
|
425
|
+
else if (cliReady && !isSubscription) {
|
|
426
|
+
// A subscription provider stays "log in" (browser-first, multi-account)
|
|
427
|
+
// even when a CLI login is on disk — reuse is offered as a secondary
|
|
428
|
+
// option inside the flow. Only a pure CLI-login provider gets rank-0.
|
|
390
429
|
rank = 0;
|
|
391
430
|
badge = "logged in — reuse, no key";
|
|
392
431
|
}
|
|
@@ -975,6 +1014,269 @@ export async function ensureSubscriptionLogin(tui, authStorage, provider) {
|
|
|
975
1014
|
return "ok";
|
|
976
1015
|
}
|
|
977
1016
|
}
|
|
1017
|
+
/** True when EITHER the operator's own `claude` login OR Brigade's managed
|
|
1018
|
+
* dedicated login is present — the backend can run with either. */
|
|
1019
|
+
function claudeCliLoggedIn() {
|
|
1020
|
+
return readClaudeCliLogin() !== null || hasBrigadeClaudeLogin();
|
|
1021
|
+
}
|
|
1022
|
+
/**
|
|
1023
|
+
* Connect the claude-cli backend end to end — no terminal, no token paste:
|
|
1024
|
+
* 1. Ensure the `claude` binary is installed (offer to `npm i -g` it).
|
|
1025
|
+
* 2. Ensure a login exists — if not, drive the SAME browser OAuth Brigade uses
|
|
1026
|
+
* for Claude Pro/Max and write the result into Brigade's OWN Claude config
|
|
1027
|
+
* dir (a dedicated grant, isolated from the operator's personal ~/.claude).
|
|
1028
|
+
* Turns then run on the Claude subscription via the binary (no extra-usage).
|
|
1029
|
+
*
|
|
1030
|
+
* Returns "ok" to proceed to model selection, or "back" to re-pick the provider.
|
|
1031
|
+
*/
|
|
1032
|
+
export async function ensureClaudeCli(tui, authStorage) {
|
|
1033
|
+
while (true) {
|
|
1034
|
+
renderScreen(tui, "Step 3 of 5 · Connect Claude");
|
|
1035
|
+
// ── 1. binary present? ──
|
|
1036
|
+
if (!isClaudeCliAvailable({ force: true })) {
|
|
1037
|
+
tui.addChild(new Text(` ${brand.white("Brigade runs on your Claude subscription via the Claude Code engine.")}`, 0, 0));
|
|
1038
|
+
tui.addChild(new Text(brand.dim(" The `claude` command isn't installed yet. Brigade can install it for you."), 0, 0));
|
|
1039
|
+
tui.addChild(new Text("", 0, 0));
|
|
1040
|
+
const choice = new SelectList([
|
|
1041
|
+
{ value: "install", label: "Install it now", description: "runs: npm i -g @anthropic-ai/claude-code" },
|
|
1042
|
+
{ value: "recheck", label: "I'll install it myself — re-check", description: "" },
|
|
1043
|
+
], 2, selectListTheme, { minPrimaryColumnWidth: 18, maxPrimaryColumnWidth: 24 });
|
|
1044
|
+
tui.addChild(choice);
|
|
1045
|
+
tui.setFocus(choice);
|
|
1046
|
+
tui.requestRender();
|
|
1047
|
+
let pick;
|
|
1048
|
+
try {
|
|
1049
|
+
const chosen = await new Promise((resolve, reject) => {
|
|
1050
|
+
choice.onSelect = (item) => resolve(item);
|
|
1051
|
+
choice.onCancel = () => reject(new Error("back"));
|
|
1052
|
+
});
|
|
1053
|
+
pick = chosen.value === "install" ? "install" : "recheck";
|
|
1054
|
+
}
|
|
1055
|
+
catch {
|
|
1056
|
+
return "back";
|
|
1057
|
+
}
|
|
1058
|
+
if (pick === "install") {
|
|
1059
|
+
renderScreen(tui, "Step 3 of 5 · Connect Claude");
|
|
1060
|
+
const loader = new CancellableLoader(tui, (s) => brand.amber(s), (s) => brand.dim(s), "Installing Claude Code (npm i -g @anthropic-ai/claude-code)…");
|
|
1061
|
+
tui.addChild(loader);
|
|
1062
|
+
tui.requestRender();
|
|
1063
|
+
const ok = await installClaudeCode();
|
|
1064
|
+
loader.stop?.();
|
|
1065
|
+
if (!ok) {
|
|
1066
|
+
renderScreen(tui, "Step 3 of 5 · Connect Claude");
|
|
1067
|
+
tui.addChild(new Text(` ${brand.error("✗")} ${brand.error("Install failed. Run `npm i -g @anthropic-ai/claude-code` manually, then Enter.")}`, 0, 0));
|
|
1068
|
+
const c = new Input();
|
|
1069
|
+
tui.addChild(c);
|
|
1070
|
+
tui.setFocus(c);
|
|
1071
|
+
tui.requestRender();
|
|
1072
|
+
try {
|
|
1073
|
+
await new Promise((res, rej) => {
|
|
1074
|
+
c.onSubmit = () => res();
|
|
1075
|
+
c.onEscape = () => rej(new Error("back"));
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1078
|
+
catch {
|
|
1079
|
+
return "back";
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
continue; // re-loop: re-check install state
|
|
1084
|
+
}
|
|
1085
|
+
// ── 2. login present? ──
|
|
1086
|
+
if (claudeCliLoggedIn()) {
|
|
1087
|
+
tui.addChild(new Text(` ${brand.amber("✓")} ${brand.dim("Claude is installed and signed in.")}`, 0, 0));
|
|
1088
|
+
tui.addChild(new Text(brand.dim(" Turns run on your Claude subscription — no key, no extra-usage billing."), 0, 0));
|
|
1089
|
+
tui.addChild(new Text("", 0, 0));
|
|
1090
|
+
tui.addChild(new Text(brand.dim(" Enter to continue · Esc to go back"), 0, 0));
|
|
1091
|
+
const confirm = new Input();
|
|
1092
|
+
tui.addChild(confirm);
|
|
1093
|
+
tui.setFocus(confirm);
|
|
1094
|
+
tui.requestRender();
|
|
1095
|
+
try {
|
|
1096
|
+
await new Promise((resolve, reject) => {
|
|
1097
|
+
confirm.onSubmit = () => resolve();
|
|
1098
|
+
confirm.onEscape = () => reject(new Error("back"));
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
catch {
|
|
1102
|
+
return "back";
|
|
1103
|
+
}
|
|
1104
|
+
return "ok";
|
|
1105
|
+
}
|
|
1106
|
+
// ── 3. no login → drive the browser OAuth ourselves, write Brigade's grant ──
|
|
1107
|
+
tui.addChild(new Text(` ${brand.white("Sign in to your Claude account")}`, 0, 0));
|
|
1108
|
+
tui.addChild(new Text(brand.dim(" We'll open your browser. Approve it there — no key, no terminal."), 0, 0));
|
|
1109
|
+
tui.addChild(new Text(brand.dim(" Enter to start · Esc to go back"), 0, 0));
|
|
1110
|
+
const start = new Input();
|
|
1111
|
+
tui.addChild(start);
|
|
1112
|
+
tui.setFocus(start);
|
|
1113
|
+
tui.requestRender();
|
|
1114
|
+
try {
|
|
1115
|
+
await new Promise((resolve, reject) => {
|
|
1116
|
+
start.onSubmit = () => resolve();
|
|
1117
|
+
start.onEscape = () => reject(new Error("back"));
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
catch {
|
|
1121
|
+
return "back";
|
|
1122
|
+
}
|
|
1123
|
+
tui.removeChild(start);
|
|
1124
|
+
const result = await runClaudeBrowserLogin(tui, authStorage);
|
|
1125
|
+
if (result === "ok") {
|
|
1126
|
+
tui.addChild(new Text("", 0, 0));
|
|
1127
|
+
tui.addChild(new Text(` ${brand.amber("✓")} Signed in — your Claude subscription is connected.`, 0, 0));
|
|
1128
|
+
tui.requestRender();
|
|
1129
|
+
await delay(600);
|
|
1130
|
+
return "ok";
|
|
1131
|
+
}
|
|
1132
|
+
if (result === "back")
|
|
1133
|
+
return "back";
|
|
1134
|
+
// "retry" → loop shows the sign-in prompt again.
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Install Claude Code globally via npm. Returns true on success. Best-effort +
|
|
1139
|
+
* bounded; surfaces nothing itself (the caller renders status).
|
|
1140
|
+
*/
|
|
1141
|
+
async function installClaudeCode() {
|
|
1142
|
+
return await new Promise((resolve) => {
|
|
1143
|
+
try {
|
|
1144
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
1145
|
+
const child = spawn(npm, ["install", "-g", "@anthropic-ai/claude-code"], {
|
|
1146
|
+
stdio: "ignore",
|
|
1147
|
+
shell: process.platform === "win32",
|
|
1148
|
+
});
|
|
1149
|
+
const timer = setTimeout(() => {
|
|
1150
|
+
try {
|
|
1151
|
+
child.kill();
|
|
1152
|
+
}
|
|
1153
|
+
catch {
|
|
1154
|
+
/* already gone */
|
|
1155
|
+
}
|
|
1156
|
+
resolve(false);
|
|
1157
|
+
}, 180_000);
|
|
1158
|
+
timer.unref?.();
|
|
1159
|
+
child.on("close", (code) => {
|
|
1160
|
+
clearTimeout(timer);
|
|
1161
|
+
resolve(code === 0 && isClaudeCliAvailable({ force: true }));
|
|
1162
|
+
});
|
|
1163
|
+
child.on("error", () => {
|
|
1164
|
+
clearTimeout(timer);
|
|
1165
|
+
resolve(false);
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
1168
|
+
catch {
|
|
1169
|
+
resolve(false);
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* Drive Brigade's browser OAuth for Anthropic (the same flow Claude Pro/Max
|
|
1175
|
+
* onboarding uses — pi-ai requests the full Claude Code scopes) and write the
|
|
1176
|
+
* result into Brigade's OWN managed Claude config dir, so the `claude` binary
|
|
1177
|
+
* authenticates + refreshes from Brigade's dedicated grant. Also mirrors the
|
|
1178
|
+
* credential into Brigade's anthropic profile so the HTTP path is available too.
|
|
1179
|
+
*
|
|
1180
|
+
* Returns "ok" on success, "back" on user abort, "retry" on a recoverable error.
|
|
1181
|
+
*/
|
|
1182
|
+
async function runClaudeBrowserLogin(tui, authStorage) {
|
|
1183
|
+
const oauthProvider = getOAuthProvider("anthropic");
|
|
1184
|
+
if (!oauthProvider) {
|
|
1185
|
+
tui.addChild(new Text(` ${brand.error("✗")} ${brand.error("Browser sign-in isn't available in this build.")}`, 0, 0));
|
|
1186
|
+
tui.requestRender();
|
|
1187
|
+
await delay(1200);
|
|
1188
|
+
return "back";
|
|
1189
|
+
}
|
|
1190
|
+
const controller = new AbortController();
|
|
1191
|
+
let creds;
|
|
1192
|
+
try {
|
|
1193
|
+
creds = (await oauthProvider.login({
|
|
1194
|
+
onAuth: (info) => {
|
|
1195
|
+
tui.addChild(new Text(` ${brand.amber("→")} Opening your browser to sign in…`, 0, 0));
|
|
1196
|
+
openSubscriptionBrowser(info.url);
|
|
1197
|
+
tui.addChild(new Text("", 0, 0));
|
|
1198
|
+
tui.addChild(new Text(" " + brand.amber(info.url), 0, 0));
|
|
1199
|
+
tui.addChild(new Text(brand.dim(" If your browser didn't open, copy the link above. Paste the code here if asked."), 0, 0));
|
|
1200
|
+
const waiter = new CancellableLoader(tui, (s) => brand.amber(s), (s) => brand.dim(s), "Waiting for you to authorize…");
|
|
1201
|
+
waiter.onAbort = () => controller.abort();
|
|
1202
|
+
tui.addChild(waiter);
|
|
1203
|
+
tui.setFocus(waiter);
|
|
1204
|
+
tui.requestRender();
|
|
1205
|
+
},
|
|
1206
|
+
onManualCodeInput: () => new Promise((resolve, reject) => {
|
|
1207
|
+
tui.addChild(new Text("", 0, 0));
|
|
1208
|
+
tui.addChild(new Text(brand.dim(" Paste the code or redirect URL, then press Enter · Esc to cancel"), 0, 0));
|
|
1209
|
+
const input = new Input();
|
|
1210
|
+
tui.addChild(input);
|
|
1211
|
+
tui.setFocus(input);
|
|
1212
|
+
tui.requestRender();
|
|
1213
|
+
input.onSubmit = (value) => resolve(sanitizePastedValue(value));
|
|
1214
|
+
input.onEscape = () => reject(new Error("cancelled"));
|
|
1215
|
+
}),
|
|
1216
|
+
onProgress: (msg) => {
|
|
1217
|
+
tui.addChild(new Text(brand.dim(" " + msg), 0, 0));
|
|
1218
|
+
tui.requestRender();
|
|
1219
|
+
},
|
|
1220
|
+
// Anthropic's loopback flow never uses these, but the callback contract
|
|
1221
|
+
// requires them — provide minimal implementations so the type + runtime
|
|
1222
|
+
// are both satisfied.
|
|
1223
|
+
onDeviceCode: () => {
|
|
1224
|
+
/* not used by the anthropic loopback flow */
|
|
1225
|
+
},
|
|
1226
|
+
onPrompt: (p) => new Promise((resolve, reject) => {
|
|
1227
|
+
tui.addChild(new Text("", 0, 0));
|
|
1228
|
+
tui.addChild(new Text(` ${p.message}`, 0, 0));
|
|
1229
|
+
const input = new Input();
|
|
1230
|
+
tui.addChild(input);
|
|
1231
|
+
tui.setFocus(input);
|
|
1232
|
+
tui.requestRender();
|
|
1233
|
+
input.onSubmit = (value) => {
|
|
1234
|
+
const v = value.trim();
|
|
1235
|
+
if (!v && !p.allowEmpty)
|
|
1236
|
+
return;
|
|
1237
|
+
resolve(v);
|
|
1238
|
+
};
|
|
1239
|
+
input.onEscape = () => reject(new Error("cancelled"));
|
|
1240
|
+
}),
|
|
1241
|
+
onSelect: (p) => new Promise((resolve) => {
|
|
1242
|
+
const list = new SelectList(p.options.map((o) => ({ value: o.id, label: o.label })), Math.min(p.options.length, 6), selectListTheme, { minPrimaryColumnWidth: 12, maxPrimaryColumnWidth: 28 });
|
|
1243
|
+
tui.addChild(list);
|
|
1244
|
+
tui.setFocus(list);
|
|
1245
|
+
tui.requestRender();
|
|
1246
|
+
list.onSelect = (item) => resolve(item.value);
|
|
1247
|
+
list.onCancel = () => resolve(undefined);
|
|
1248
|
+
}),
|
|
1249
|
+
signal: controller.signal,
|
|
1250
|
+
}));
|
|
1251
|
+
}
|
|
1252
|
+
catch (err) {
|
|
1253
|
+
controller.abort();
|
|
1254
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
1255
|
+
const softCancel = /^login cancelled$/i.test(reason) || reason === "cancelled" || reason === "back";
|
|
1256
|
+
tui.addChild(new Text(` ${brand.error("✗")} ${brand.error(softCancel ? "Sign-in cancelled." : "Couldn't finish signing in — check your connection and try again.")}`, 0, 0));
|
|
1257
|
+
tui.requestRender();
|
|
1258
|
+
await delay(1000);
|
|
1259
|
+
return softCancel ? "back" : "retry";
|
|
1260
|
+
}
|
|
1261
|
+
// Write Brigade's dedicated Claude login ONLY into the managed config dir.
|
|
1262
|
+
// The `claude` binary owns this grant from here on: it authenticates AND
|
|
1263
|
+
// refreshes (rotating the refresh token) in-place. We deliberately DON'T
|
|
1264
|
+
// also mirror it into Brigade's anthropic auth-profile — that would create a
|
|
1265
|
+
// SECOND independent refresher (Brigade's HTTP-path backend) for the same
|
|
1266
|
+
// grant, and the two would rotate each other's refresh token to death
|
|
1267
|
+
// (the split-brain failure). Single grant, single owner (the binary).
|
|
1268
|
+
void authStorage; // intentionally unused now — kept for signature stability
|
|
1269
|
+
try {
|
|
1270
|
+
writeBrigadeClaudeCredential({ access: creds.access, refresh: creds.refresh, expires: creds.expires });
|
|
1271
|
+
}
|
|
1272
|
+
catch (err) {
|
|
1273
|
+
tui.addChild(new Text(` ${brand.error("✗")} ${brand.error(`Couldn't save the login: ${err.message}`)}`, 0, 0));
|
|
1274
|
+
tui.requestRender();
|
|
1275
|
+
await delay(1200);
|
|
1276
|
+
return "retry";
|
|
1277
|
+
}
|
|
1278
|
+
return "ok";
|
|
1279
|
+
}
|
|
978
1280
|
/**
|
|
979
1281
|
* Connect a subscription provider that ALSO has a vendor CLI login on disk
|
|
980
1282
|
* (Claude Code / Codex). When such a login exists we present a choice that LEADS
|
|
@@ -1027,6 +1329,12 @@ async function ensureCliLogin(tui, authStorage, provider) {
|
|
|
1027
1329
|
access: cred.access,
|
|
1028
1330
|
refresh: cred.refresh,
|
|
1029
1331
|
expires: cred.expires,
|
|
1332
|
+
// Borrowed from the vendor CLI's on-disk login — mark the family so
|
|
1333
|
+
// `adoptNewerClaudeCliLogin` keeps adopting the CLI's rotations
|
|
1334
|
+
// instead of refreshing (and rotating) a stale shared grant.
|
|
1335
|
+
...(provider.cliLogin.read === "claude"
|
|
1336
|
+
? { metadata: { importedFrom: "claude-cli" } }
|
|
1337
|
+
: {}),
|
|
1030
1338
|
});
|
|
1031
1339
|
authStorage.set(cred.provider, {
|
|
1032
1340
|
type: "oauth",
|
|
@@ -1330,6 +1638,37 @@ async function pickModel(tui, modelRegistry, providerId) {
|
|
|
1330
1638
|
return "back";
|
|
1331
1639
|
}
|
|
1332
1640
|
}
|
|
1641
|
+
/** Model picker for the claude-cli backend — its models are synthesized (not in
|
|
1642
|
+
* the registry), so we present the backend's own catalog. */
|
|
1643
|
+
async function pickClaudeCliModel(tui) {
|
|
1644
|
+
const items = CLAUDE_CLI_MODELS.map((m) => ({
|
|
1645
|
+
value: m.id,
|
|
1646
|
+
label: m.id,
|
|
1647
|
+
description: m.name,
|
|
1648
|
+
}));
|
|
1649
|
+
// Default first = the catalog default (Sonnet), then the rest as listed.
|
|
1650
|
+
items.sort((a, b) => a.value === CLAUDE_CLI_DEFAULT_MODEL ? -1 : b.value === CLAUDE_CLI_DEFAULT_MODEL ? 1 : 0);
|
|
1651
|
+
const list = new SearchableSelectList(items, 8, selectListTheme, {
|
|
1652
|
+
minPrimaryColumnWidth: 26,
|
|
1653
|
+
maxPrimaryColumnWidth: 38,
|
|
1654
|
+
formatHeader: (q, matchCount, total) => brand.dim(q.length > 0
|
|
1655
|
+
? ` search: ${q}▌ (${matchCount}/${total})`
|
|
1656
|
+
: ` ${total} models · ↑↓ move · Enter select · Esc back`),
|
|
1657
|
+
});
|
|
1658
|
+
tui.addChild(list);
|
|
1659
|
+
tui.setFocus(list);
|
|
1660
|
+
tui.requestRender();
|
|
1661
|
+
try {
|
|
1662
|
+
const chosen = await new Promise((resolve, reject) => {
|
|
1663
|
+
list.onSelect = (item) => resolve(item);
|
|
1664
|
+
list.onCancel = () => reject(new Error("back"));
|
|
1665
|
+
});
|
|
1666
|
+
return { modelId: chosen.value };
|
|
1667
|
+
}
|
|
1668
|
+
catch {
|
|
1669
|
+
return "back";
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1333
1672
|
function renderDone(tui, provider, modelId) {
|
|
1334
1673
|
const p = findProvider(provider)?.name ?? provider;
|
|
1335
1674
|
tui.addChild(new Text("", 0, 0));
|