@spinabot/brigade 1.23.0 → 1.24.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/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
|
@@ -22,12 +22,62 @@
|
|
|
22
22
|
* impossible (no template + no provider config) — the only legitimate miss.
|
|
23
23
|
*/
|
|
24
24
|
import * as fs from "node:fs";
|
|
25
|
+
import { isClaudeCliProvider, synthClaudeCliModel } from "./claude-cli/register.js";
|
|
25
26
|
import { isLikelyReasoningModelId } from "../core/model-caps.js";
|
|
26
27
|
import { rediscoverOllamaModel } from "../integrations/ollama.js";
|
|
27
28
|
import { discoverCloudModelMeta } from "../integrations/provider-discovery.js";
|
|
28
29
|
const DEFAULT_CONTEXT_WINDOW = 200_000;
|
|
29
30
|
const DEFAULT_MAX_TOKENS = 8192;
|
|
30
31
|
const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
32
|
+
/**
|
|
33
|
+
* Per-provider context window INCLUDED in a subscription login. A request whose
|
|
34
|
+
* input exceeds this draws from that provider's pay-as-you-go / overage bucket
|
|
35
|
+
* ("extra usage", "credits") instead of the flat plan — even while the plan's
|
|
36
|
+
* session/weekly quota is untouched.
|
|
37
|
+
*
|
|
38
|
+
* Only list a provider whose subscription ACTUALLY bills long context as overage.
|
|
39
|
+
* A provider whose subscription is purely rate/quota-limited (a message cap, a
|
|
40
|
+
* requests-per-window limit — no per-token-context overage) must NOT be listed,
|
|
41
|
+
* or we'd compact early for zero billing benefit and hurt its UX. Add a provider
|
|
42
|
+
* here only once its overage-context boundary is confirmed.
|
|
43
|
+
*
|
|
44
|
+
* anthropic — Claude Pro/Max include the 200K standard window; a request >200K
|
|
45
|
+
* uses the long-context (1M) capability, billed as extra usage.
|
|
46
|
+
* Catalogued models such as claude-opus-4-8 carry a 1,000,000
|
|
47
|
+
* window, so without this clamp pre-emptive compaction wouldn't
|
|
48
|
+
* fire until ~850K tokens (0.85 × 1M) and every large turn would
|
|
49
|
+
* sail past 200K into extra usage (the "You're out of extra usage"
|
|
50
|
+
* 400 seen with plenty of plan left).
|
|
51
|
+
*/
|
|
52
|
+
export const SUBSCRIPTION_INCLUDED_CONTEXT_WINDOW = {
|
|
53
|
+
anthropic: 200_000,
|
|
54
|
+
};
|
|
55
|
+
/** Back-compat alias for the Anthropic included-tier boundary. */
|
|
56
|
+
export const ANTHROPIC_SUBSCRIPTION_CONTEXT_WINDOW = SUBSCRIPTION_INCLUDED_CONTEXT_WINDOW.anthropic;
|
|
57
|
+
/**
|
|
58
|
+
* The context window a request should be SIZED against for billing safety.
|
|
59
|
+
*
|
|
60
|
+
* On a subscription login (OAuth / setup-token) the window is capped to the
|
|
61
|
+
* provider's included tier (see `SUBSCRIPTION_INCLUDED_CONTEXT_WINDOW`), so
|
|
62
|
+
* pre-emptive compaction fires before a request crosses into overage territory
|
|
63
|
+
* and the operator never draws pay-as-you-go credits while their plan has room.
|
|
64
|
+
* For API-key auth (pay-per-token — no overage concept), for a subscription
|
|
65
|
+
* provider we haven't confirmed has a context-overage boundary, and for any
|
|
66
|
+
* window already inside the included tier, the model's real window is returned
|
|
67
|
+
* unchanged. Provider-generic + pure.
|
|
68
|
+
*/
|
|
69
|
+
export function billingSafeContextWindow(provider, contextWindow, isSubscription) {
|
|
70
|
+
if (!isSubscription)
|
|
71
|
+
return contextWindow;
|
|
72
|
+
const included = SUBSCRIPTION_INCLUDED_CONTEXT_WINDOW[provider];
|
|
73
|
+
if (included !== undefined &&
|
|
74
|
+
typeof contextWindow === "number" &&
|
|
75
|
+
Number.isFinite(contextWindow) &&
|
|
76
|
+
contextWindow > included) {
|
|
77
|
+
return included;
|
|
78
|
+
}
|
|
79
|
+
return contextWindow;
|
|
80
|
+
}
|
|
31
81
|
/**
|
|
32
82
|
* Resolve `provider/modelId` to a usable Model, discovering or synthesizing
|
|
33
83
|
* one on a static miss. See module header for the ordered net.
|
|
@@ -37,6 +87,15 @@ export async function resolveModelNeverMiss(args) {
|
|
|
37
87
|
const registry = args.modelRegistry;
|
|
38
88
|
if (typeof registry.find !== "function")
|
|
39
89
|
return undefined;
|
|
90
|
+
// 0. claude-cli backend — a subprocess transport, not an HTTP provider, so
|
|
91
|
+
// its models never live in Pi's catalog or models.json. Synthesize directly
|
|
92
|
+
// so `claude-cli/<model>` always resolves to an `api: "claude-cli"` Model
|
|
93
|
+
// (the registered transport dispatches it; the CLI validates the concrete id
|
|
94
|
+
// at spawn time). Checked FIRST so a stray built-in `claude-*` catalog entry
|
|
95
|
+
// can't shadow the subscription backend.
|
|
96
|
+
if (isClaudeCliProvider(provider)) {
|
|
97
|
+
return synthClaudeCliModel(modelId);
|
|
98
|
+
}
|
|
40
99
|
// 1. Static.
|
|
41
100
|
const direct = registry.find(provider, modelId);
|
|
42
101
|
if (direct)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-resolution.js","sourceRoot":"","sources":["../../src/agents/model-resolution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAE9B,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,sBAAsB,EAA4B,MAAM,uCAAuC,CAAC;AAEzG,MAAM,sBAAsB,GAAG,OAAO,CAAC;AACvC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,SAAS,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"model-resolution.js","sourceRoot":"","sources":["../../src/agents/model-resolution.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry-policy.d.ts","sourceRoot":"","sources":["../../src/agents/retry-policy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"retry-policy.d.ts","sourceRoot":"","sources":["../../src/agents/retry-policy.ts"],"names":[],"mappings":"AAyBA,OAAO,EAIL,KAAK,qBAAqB,EAC1B,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAE/B,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,EAAE,OAAO,CAAC;IAIrB,iBAAiB,EAAE,OAAO,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CA8I/D;AAYD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAKlF;AAWD,wBAAgB,4BAA4B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAGzE;AAUD,MAAM,WAAW,gBAAgB,CAAC,CAAC;IAEjC,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAEpE,GAAG,CAAC,EAAE,qBAAqB,CAAC;IAE5B,MAAM,CAAC,EAAE,WAAW,CAAC;IAKrB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrE;AAED,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,WAAW,CAAC;gBAErB,QAAQ,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,OAAO;CAyB9D;AAED;sEACsE;AACtE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,mBAAmB,CAIlF;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAkE3E"}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
// timeout yes 3 1s+jitter yes econn*, deadline
|
|
15
15
|
// unknown yes 2 1s+jitter yes collapse-into-retry
|
|
16
16
|
// billing no 0 n/a rotate-model 402 → failover chain / surface
|
|
17
|
+
// subscription_limit no 0 n/a rotate-model plan window exhausted → failover chain / surface
|
|
17
18
|
// format no 0 n/a n/a same body re-fails
|
|
18
19
|
// model_not_found no 0 n/a rotate-model fallback chain
|
|
19
20
|
// auth no 0 n/a yes try other profile
|
|
@@ -80,6 +81,23 @@ export function getRetryPolicy(reason) {
|
|
|
80
81
|
rotateModel: true,
|
|
81
82
|
consumesProbeSlot: false,
|
|
82
83
|
};
|
|
84
|
+
case "subscription_limit":
|
|
85
|
+
// The subscription plan's usage window (e.g. Claude Max 5-hour /
|
|
86
|
+
// weekly) is exhausted. Same-model retry is guaranteed to re-fail
|
|
87
|
+
// until the window resets on its own wall clock — hours, not seconds
|
|
88
|
+
// — and rotating auth profiles doesn't help (same account, same
|
|
89
|
+
// window). Fail fast and let the model fallback chain try a
|
|
90
|
+
// different (provider, model); with no fallback configured the error
|
|
91
|
+
// surfaces immediately with the reset hint (see RetryExhaustedError).
|
|
92
|
+
return {
|
|
93
|
+
reason,
|
|
94
|
+
transient: false,
|
|
95
|
+
maxRetries: 0,
|
|
96
|
+
baseBackoffMs: 0,
|
|
97
|
+
rotateAuthProfile: false,
|
|
98
|
+
rotateModel: true,
|
|
99
|
+
consumesProbeSlot: false,
|
|
100
|
+
};
|
|
83
101
|
case "format":
|
|
84
102
|
return {
|
|
85
103
|
reason,
|
|
@@ -182,12 +200,18 @@ export class RetryExhaustedError extends Error {
|
|
|
182
200
|
const last = attempts[attempts.length - 1];
|
|
183
201
|
const lastReason = last?.reason ?? "unknown";
|
|
184
202
|
const summary = last?.errorSummary ?? (lastError instanceof Error ? lastError.message : String(lastError));
|
|
203
|
+
// Operator-facing hint: a subscription-window error otherwise reads like
|
|
204
|
+
// "buy credits", which sends the operator to the wrong fix (topping up an
|
|
205
|
+
// API account) when the real state is "plan window used up, resets soon".
|
|
206
|
+
const hint = lastReason === "subscription_limit"
|
|
207
|
+
? "\nYour subscription's usage window is used up — it resets on its own (check /usage or claude.ai/settings/usage). This is the plan limit, not missing API credits."
|
|
208
|
+
: "";
|
|
185
209
|
// Chain the underlying error as `cause`. Recipient-facing classification
|
|
186
210
|
// walks `.cause` to find a known reason; without this, a 402 OpenRouter
|
|
187
211
|
// billing error wrapped in a retry-exhausted shell was being classified
|
|
188
212
|
// as `unknown` and recipients got the generic "Sorry I hit an error"
|
|
189
213
|
// reply instead of the friendly "I'm out of credits" message.
|
|
190
|
-
super(`Retry exhausted after ${attempts.length} attempt(s); last reason=${lastReason}: ${summary}`, lastError instanceof Error ? { cause: lastError } : undefined);
|
|
214
|
+
super(`Retry exhausted after ${attempts.length} attempt(s); last reason=${lastReason}: ${summary}${hint}`, lastError instanceof Error ? { cause: lastError } : undefined);
|
|
191
215
|
this.name = "RetryExhaustedError";
|
|
192
216
|
this.attempts = attempts;
|
|
193
217
|
this.lastReason = lastReason;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry-policy.js","sourceRoot":"","sources":["../../src/agents/retry-policy.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"retry-policy.js","sourceRoot":"","sources":["../../src/agents/retry-policy.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,gDAAgD;AAChD,EAAE;AACF,sEAAsE;AACtE,gBAAgB;AAChB,EAAE;AACF,6EAA6E;AAC7E,4EAA4E;AAC5E,kFAAkF;AAClF,kFAAkF;AAClF,yFAAyF;AACzF,4FAA4F;AAC5F,uGAAuG;AACvG,yHAAyH;AACzH,2FAA2F;AAC3F,uFAAuF;AACvF,0FAA0F;AAC1F,wFAAwF;AACxF,+FAA+F;AAE/F,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,GAGf,MAAM,uBAAuB,CAAC;AAe/B,MAAM,UAAU,cAAc,CAAC,MAAmB;IAChD,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,YAAY;YACf,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,KAAK;gBACpB,iBAAiB,EAAE,IAAI;gBACvB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,IAAI;aACxB,CAAC;QACJ,KAAK,YAAY;YACf,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,KAAK;gBACpB,iBAAiB,EAAE,IAAI;gBACvB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,IAAI;aACxB,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,KAAK;gBACpB,iBAAiB,EAAE,IAAI;gBACvB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,IAAI;aACxB,CAAC;QACJ,KAAK,SAAS;YACZ,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,KAAK;gBACpB,iBAAiB,EAAE,IAAI;gBACvB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,IAAI;aACxB,CAAC;QACJ,KAAK,SAAS;YACZ,mEAAmE;YACnE,+DAA+D;YAC/D,gEAAgE;YAChE,mEAAmE;YACnE,+DAA+D;YAC/D,4DAA4D;YAC5D,yDAAyD;YACzD,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,IAAI;gBACjB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,oBAAoB;YACvB,iEAAiE;YACjE,kEAAkE;YAClE,qEAAqE;YACrE,gEAAgE;YAChE,4DAA4D;YAC5D,qEAAqE;YACrE,sEAAsE;YACtE,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,IAAI;gBACjB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,QAAQ;YACX,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,iBAAiB;YACpB,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,IAAI;gBACjB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,MAAM;YACT,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,IAAI;gBACvB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,gBAAgB;YACnB,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,iBAAiB;YACpB,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,KAAK;aACzB,CAAC;QACJ,KAAK,kBAAkB;YACrB,sEAAsE;YACtE,uEAAuE;YACvE,mEAAmE;YACnE,wEAAwE;YACxE,kEAAkE;YAClE,OAAO;gBACL,MAAM;gBACN,SAAS,EAAE,IAAI;gBACf,UAAU,EAAE,CAAC;gBACb,aAAa,EAAE,CAAC;gBAChB,iBAAiB,EAAE,KAAK;gBACxB,WAAW,EAAE,KAAK;gBAClB,iBAAiB,EAAE,KAAK;aACzB,CAAC;IACN,CAAC;AACH,CAAC;AAED,gFAAgF;AAChF,wEAAwE;AACxE,MAAM,cAAc,GAAG,MAAM,CAAC;AAC9B,4EAA4E;AAC5E,wEAAwE;AACxE,2EAA2E;AAC3E,mEAAmE;AACnE,gDAAgD;AAChD,MAAM,oBAAoB,GAAG,EAAE,CAAC;AAEhC,MAAM,UAAU,gBAAgB,CAAC,MAAmB,EAAE,YAAoB;IACxE,IAAI,MAAM,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC9E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,aAAa,GAAG,CAAC,IAAI,WAAW,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,yEAAyE;AACzE,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,SAAS,GAAG,GAAG,CAAC;AAEtB,MAAM,UAAU,4BAA4B,CAAC,YAAoB;IAC/D,MAAM,MAAM,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,GAAG,iBAAiB,CAAC;IAC1E,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;AAC1D,CAAC;AAkCD,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,QAAQ,CAAsB;IAC9B,UAAU,CAAc;IAEjC,YAAY,QAA6B,EAAE,SAAkB;QAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,MAAM,UAAU,GAAgB,IAAI,EAAE,MAAM,IAAI,SAAS,CAAC;QAC1D,MAAM,OAAO,GACX,IAAI,EAAE,YAAY,IAAI,CAAC,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7F,yEAAyE;QACzE,0EAA0E;QAC1E,0EAA0E;QAC1E,MAAM,IAAI,GACR,UAAU,KAAK,oBAAoB;YACjC,CAAC,CAAC,mKAAmK;YACrK,CAAC,CAAC,EAAE,CAAC;QACT,yEAAyE;QACzE,wEAAwE;QACxE,wEAAwE;QACxE,qEAAqE;QACrE,8DAA8D;QAC9D,KAAK,CACH,yBAAyB,QAAQ,CAAC,MAAM,4BAA4B,UAAU,KAAK,OAAO,GAAG,IAAI,EAAE,EACnG,SAAS,YAAY,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9D,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF;AAED;sEACsE;AACtE,MAAM,UAAU,qBAAqB,CAAC,KAAc;IAClD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAiD,CAAC;IAC5D,OAAO,CAAC,CAAC,IAAI,KAAK,qBAAqB,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAI,IAAyB;IAC7D,MAAM,QAAQ,GAAwB,EAAE,CAAC;IACzC,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,OAAO,IAAI,EAAE,CAAC;QACZ,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YACzB,qEAAqE;YACrE,8CAA8C;YAC9C,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,sEAAsE;YACtE,IAAI,YAAY,CAAC,GAAG,CAAC;gBAAE,MAAM,GAAG,CAAC;YACjC,gEAAgE;YAChE,mEAAmE;YACnE,mEAAmE;YACnE,+DAA+D;YAC/D,kEAAkE;YAClE,qDAAqD;YACrD,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO;gBAAE,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC;YAE1D,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;YAClD,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YACtC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,GAAG,YAAY,CAAC;YACnD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,SAAS,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;YAC7E,MAAM,SAAS,GAAG,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAEzE,MAAM,IAAI,GAAsB;gBAC9B,YAAY;gBACZ,MAAM;gBACN,MAAM;gBACN,SAAS;gBACT,SAAS;gBACT,YAAY,EAAE,cAAc,CAAC,GAAG,CAAC;gBACjC,KAAK,EAAE,GAAG;aACX,CAAC;YACF,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpB,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC;YACpD,IAAI,cAAc,IAAI,OAAQ,cAAgC,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBACnF,IAAI,CAAC;oBACH,MAAM,cAAc,CAAC;gBACvB,CAAC;gBAAC,MAAM,CAAC;oBACP,6DAA6D;gBAC/D,CAAC;YACH,CAAC;YAED,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,IAAI,mBAAmB,CAAC,GAAG,CAAC;oBAAE,MAAM,GAAG,CAAC;gBACxC,MAAM,IAAI,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;YAC/C,CAAC;YAED,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBAClB,IAAI,CAAC;oBACH,MAAM,KAAK,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;gBAC7D,CAAC;gBAAC,MAAM,CAAC;oBACP,qEAAqE;oBACrE,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,YAAY,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAA2C,CAAC;IACtD,OAAO,CAAC,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,IAAI,KAAK,WAAW,IAAI,CAAC,CAAC,IAAI,KAAK,EAAE,CAAC;AAC5E,CAAC"}
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* BOTH filesystem and Convex mode (it never touches a raw file or the store
|
|
20
20
|
* adapter directly).
|
|
21
21
|
*/
|
|
22
|
+
import { readClaudeCliLogin } from "../integrations/cli-login.js";
|
|
22
23
|
export interface UnrefreshableSubscription {
|
|
23
24
|
/** Stored provider id (where the credential lives, e.g. "anthropic"). */
|
|
24
25
|
provider: string;
|
|
@@ -63,6 +64,94 @@ export declare function detectUnrefreshableSubscriptions(agentId?: string): Unre
|
|
|
63
64
|
* warns). Returns the provider labels it healed, for a one-line boot log.
|
|
64
65
|
*/
|
|
65
66
|
export declare function autoHealSubscriptions(agentId?: string): string[];
|
|
67
|
+
/**
|
|
68
|
+
* SPLIT-BRAIN GUARD for credentials borrowed from the Claude Code CLI.
|
|
69
|
+
*
|
|
70
|
+
* When Brigade adopts the CLI's login (onboarding "reuse this machine's
|
|
71
|
+
* login" / `autoHealSubscriptions`), BOTH processes end up holding the same
|
|
72
|
+
* OAuth grant — and each refresh ROTATES the refresh token. The vendor CLI
|
|
73
|
+
* refreshes constantly as the operator uses it, so Brigade's stored copy
|
|
74
|
+
* goes stale within hours; when Brigade later refreshes its stale copy the
|
|
75
|
+
* two logins race and one of them dies (the recurring "login dropped" bug,
|
|
76
|
+
* this time across processes rather than restarts).
|
|
77
|
+
*
|
|
78
|
+
* This sync runs at every credential-map build (per turn + boot): if the
|
|
79
|
+
* stored anthropic profile is the SAME grant family as the CLI file and the
|
|
80
|
+
* CLI holds a NEWER access token, adopt the CLI's tokens instead of
|
|
81
|
+
* refreshing our stale ones. Brigade then only performs its own refresh when
|
|
82
|
+
* the CLI has been idle past expiry — the narrowest window we can get
|
|
83
|
+
* without writing the vendor CLI's credential file.
|
|
84
|
+
*
|
|
85
|
+
* Same-family detection: the `importedFrom: "claude-cli"` metadata stamp, or
|
|
86
|
+
* (for profiles imported before the stamp existed) literal access/refresh
|
|
87
|
+
* token equality — in which case the stamp is added so the link survives
|
|
88
|
+
* future rotation divergence. A profile from an independent `brigade login`
|
|
89
|
+
* browser grant carries neither and is never touched.
|
|
90
|
+
*
|
|
91
|
+
* Best-effort + defensive like the rest of this module: any read/parse
|
|
92
|
+
* failure is a no-op. Returns true when newer CLI tokens were adopted.
|
|
93
|
+
*/
|
|
94
|
+
export declare function adoptNewerClaudeCliLogin(agentId?: string): boolean;
|
|
95
|
+
export type DeadLoginHealResult = "refreshed" | "adopted" | "none";
|
|
96
|
+
interface HealRefreshedTokens {
|
|
97
|
+
access: string;
|
|
98
|
+
refresh: string;
|
|
99
|
+
expires: number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* LAST-RESORT heal for a subscription login whose access token has expired.
|
|
103
|
+
*
|
|
104
|
+
* `adoptNewerClaudeCliLogin` covers borrowed logins it can LINK to the CLI
|
|
105
|
+
* file (metadata stamp or token equality). But a profile that diverged
|
|
106
|
+
* BEFORE the stamp existed — the CLI rotated the shared grant while Brigade
|
|
107
|
+
* held the old copy — matches nothing: its access token is expired, its
|
|
108
|
+
* refresh token was invalidated by the rotation, and Pi's refresh dies with
|
|
109
|
+
* "No API key for provider". This function recovers that state without
|
|
110
|
+
* guessing:
|
|
111
|
+
*
|
|
112
|
+
* 1. Try a REAL refresh with the stored refresh token. If it succeeds the
|
|
113
|
+
* grant is alive (an independent `brigade login`, or a borrow the
|
|
114
|
+
* vendor still honours) — persist the rotated tokens and stop. An
|
|
115
|
+
* independent grant is never clobbered by adoption.
|
|
116
|
+
* 2. Only when the refresh is REJECTED (grant dead) adopt the machine's
|
|
117
|
+
* Claude Code CLI login — the same choice the operator made when they
|
|
118
|
+
* picked "reuse this machine's login" — and stamp the family link so
|
|
119
|
+
* the per-turn sync keeps it fresh from now on.
|
|
120
|
+
* 3. No CLI login to adopt → "none"; the auth error surfaces normally.
|
|
121
|
+
*
|
|
122
|
+
* Network I/O happens ONLY when the stored access token is already expired
|
|
123
|
+
* (a state that otherwise guarantees a failed turn). Concurrent calls for
|
|
124
|
+
* the same agent are coalesced. Best-effort: any failure returns "none".
|
|
125
|
+
*/
|
|
126
|
+
export declare function healDeadSubscriptionLogin(agentId?: string, opts?: {
|
|
127
|
+
/** Injectable for tests — performs the OAuth refresh, null on rejection. */
|
|
128
|
+
refreshFn?: (refreshToken: string) => Promise<HealRefreshedTokens | null>;
|
|
129
|
+
/** Injectable for tests — reads the vendor CLI login file. */
|
|
130
|
+
cliRead?: typeof readClaudeCliLogin;
|
|
131
|
+
nowMs?: number;
|
|
132
|
+
}): Promise<DeadLoginHealResult>;
|
|
133
|
+
/** The stored-profile fields the adoption decision inspects. */
|
|
134
|
+
export interface CliAdoptionProfile {
|
|
135
|
+
access?: string;
|
|
136
|
+
refresh?: string;
|
|
137
|
+
expires?: number;
|
|
138
|
+
metadata?: Record<string, unknown>;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Pure decision core for `adoptNewerClaudeCliLogin` (unit-testable without
|
|
142
|
+
* storage or the CLI file):
|
|
143
|
+
* - "adopt" — same grant family and the CLI holds newer tokens.
|
|
144
|
+
* - "stamp" — same family, nothing newer, but the profile predates the
|
|
145
|
+
* `importedFrom` stamp; write the stamp so the link survives divergence.
|
|
146
|
+
* - "none" — different grant (independent `brigade login`) or already
|
|
147
|
+
* up to date and stamped.
|
|
148
|
+
*/
|
|
149
|
+
export declare function decideCliLoginAdoption(prof: CliAdoptionProfile, cli: {
|
|
150
|
+
access: string;
|
|
151
|
+
refresh: string;
|
|
152
|
+
expires?: number;
|
|
153
|
+
}): "adopt" | "stamp" | "none";
|
|
66
154
|
/** One-line-per-provider operator warning, or "" when healthy. */
|
|
67
155
|
export declare function formatUnrefreshableWarning(list: readonly UnrefreshableSubscription[]): string;
|
|
156
|
+
export {};
|
|
68
157
|
//# sourceMappingURL=auth-health.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-health.d.ts","sourceRoot":"","sources":["../../src/auth/auth-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;
|
|
1
|
+
{"version":3,"file":"auth-health.d.ts","sourceRoot":"","sources":["../../src/auth/auth-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAIlE,MAAM,WAAW,yBAAyB;IACzC,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;CACf;AAED,yDAAyD;AACzD,MAAM,WAAW,kBAAkB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAkBnF;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC/C,OAAO,GAAE,MAAyB,GAChC,yBAAyB,EAAE,CA+B7B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,MAAyB,GAAG,MAAM,EAAE,CAsBlF;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,MAAyB,GAAG,OAAO,CA+BpF;AAQD,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,UAAU,mBAAmB;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,yBAAyB,CAC9C,OAAO,GAAE,MAAyB,EAClC,IAAI,GAAE;IACL,4EAA4E;IAC5E,SAAS,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC1E,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,kBAAkB,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CACV,GACJ,OAAO,CAAC,mBAAmB,CAAC,CAQ9B;AAmGD,gEAAgE;AAChE,MAAM,WAAW,kBAAkB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACrC,IAAI,EAAE,kBAAkB,EACxB,GAAG,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACxD,OAAO,GAAG,OAAO,GAAG,MAAM,CAa5B;AAED,kEAAkE;AAClE,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,SAAS,yBAAyB,EAAE,GAAG,MAAM,CAQ7F"}
|
package/dist/auth/auth-health.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
import { DEFAULT_AGENT_ID } from "../config/paths.js";
|
|
23
23
|
import { readClaudeCliLogin } from "../integrations/cli-login.js";
|
|
24
24
|
import { PROVIDERS } from "../providers/catalog.js";
|
|
25
|
-
import { readProfiles, upsertOAuthProfile } from "./profiles.js";
|
|
25
|
+
import { readProfiles, updateOAuthTokens, upsertOAuthProfile } from "./profiles.js";
|
|
26
26
|
/**
|
|
27
27
|
* Classify whether a stored profile can auto-refresh. Returns the human reason
|
|
28
28
|
* it CAN'T (for warnings), or null when the credential is healthy. Pure — unit
|
|
@@ -111,12 +111,218 @@ export function autoHealSubscriptions(agentId = DEFAULT_AGENT_ID) {
|
|
|
111
111
|
access: cli.access,
|
|
112
112
|
refresh: cli.refresh,
|
|
113
113
|
...(cli.expires !== undefined ? { expires: cli.expires } : {}),
|
|
114
|
+
// Mark the credential as borrowed from the vendor CLI so
|
|
115
|
+
// `adoptNewerClaudeCliLogin` keeps it synced with the CLI's own
|
|
116
|
+
// rotations from here on.
|
|
117
|
+
metadata: { importedFrom: "claude-cli" },
|
|
114
118
|
});
|
|
115
119
|
healed.push(sub.label);
|
|
116
120
|
}
|
|
117
121
|
}
|
|
118
122
|
return healed;
|
|
119
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* SPLIT-BRAIN GUARD for credentials borrowed from the Claude Code CLI.
|
|
126
|
+
*
|
|
127
|
+
* When Brigade adopts the CLI's login (onboarding "reuse this machine's
|
|
128
|
+
* login" / `autoHealSubscriptions`), BOTH processes end up holding the same
|
|
129
|
+
* OAuth grant — and each refresh ROTATES the refresh token. The vendor CLI
|
|
130
|
+
* refreshes constantly as the operator uses it, so Brigade's stored copy
|
|
131
|
+
* goes stale within hours; when Brigade later refreshes its stale copy the
|
|
132
|
+
* two logins race and one of them dies (the recurring "login dropped" bug,
|
|
133
|
+
* this time across processes rather than restarts).
|
|
134
|
+
*
|
|
135
|
+
* This sync runs at every credential-map build (per turn + boot): if the
|
|
136
|
+
* stored anthropic profile is the SAME grant family as the CLI file and the
|
|
137
|
+
* CLI holds a NEWER access token, adopt the CLI's tokens instead of
|
|
138
|
+
* refreshing our stale ones. Brigade then only performs its own refresh when
|
|
139
|
+
* the CLI has been idle past expiry — the narrowest window we can get
|
|
140
|
+
* without writing the vendor CLI's credential file.
|
|
141
|
+
*
|
|
142
|
+
* Same-family detection: the `importedFrom: "claude-cli"` metadata stamp, or
|
|
143
|
+
* (for profiles imported before the stamp existed) literal access/refresh
|
|
144
|
+
* token equality — in which case the stamp is added so the link survives
|
|
145
|
+
* future rotation divergence. A profile from an independent `brigade login`
|
|
146
|
+
* browser grant carries neither and is never touched.
|
|
147
|
+
*
|
|
148
|
+
* Best-effort + defensive like the rest of this module: any read/parse
|
|
149
|
+
* failure is a no-op. Returns true when newer CLI tokens were adopted.
|
|
150
|
+
*/
|
|
151
|
+
export function adoptNewerClaudeCliLogin(agentId = DEFAULT_AGENT_ID) {
|
|
152
|
+
try {
|
|
153
|
+
const cli = readClaudeCliLogin();
|
|
154
|
+
if (!cli || cli.type !== "oauth" || !cli.access || !cli.refresh)
|
|
155
|
+
return false;
|
|
156
|
+
const file = readProfiles(agentId);
|
|
157
|
+
const prof = Object.values(file.profiles ?? {}).find((p) => p?.provider === "anthropic" && p?.type === "oauth");
|
|
158
|
+
if (!prof)
|
|
159
|
+
return false;
|
|
160
|
+
const decision = decideCliLoginAdoption(prof, cli);
|
|
161
|
+
if (decision === "stamp") {
|
|
162
|
+
// Nothing newer to adopt — but stamp the family link once so a future
|
|
163
|
+
// rotation on either side can't sever it.
|
|
164
|
+
updateOAuthTokens(agentId, "anthropic", { metadata: { importedFrom: "claude-cli" } });
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
if (decision !== "adopt")
|
|
168
|
+
return false;
|
|
169
|
+
updateOAuthTokens(agentId, "anthropic", {
|
|
170
|
+
access: cli.access,
|
|
171
|
+
refresh: cli.refresh,
|
|
172
|
+
expires: cli.expires,
|
|
173
|
+
metadata: { importedFrom: "claude-cli" },
|
|
174
|
+
});
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const ANTHROPIC_OAUTH_TOKEN_URL = "https://console.anthropic.com/v1/oauth/token";
|
|
182
|
+
// Claude Code's public OAuth client id — the same client the vendor CLI and
|
|
183
|
+
// its IDE extensions use (it's echoed back in every /api/oauth/profile
|
|
184
|
+
// response as `application.uuid`). Needed to refresh a subscription grant.
|
|
185
|
+
const CLAUDE_CODE_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
186
|
+
/**
|
|
187
|
+
* LAST-RESORT heal for a subscription login whose access token has expired.
|
|
188
|
+
*
|
|
189
|
+
* `adoptNewerClaudeCliLogin` covers borrowed logins it can LINK to the CLI
|
|
190
|
+
* file (metadata stamp or token equality). But a profile that diverged
|
|
191
|
+
* BEFORE the stamp existed — the CLI rotated the shared grant while Brigade
|
|
192
|
+
* held the old copy — matches nothing: its access token is expired, its
|
|
193
|
+
* refresh token was invalidated by the rotation, and Pi's refresh dies with
|
|
194
|
+
* "No API key for provider". This function recovers that state without
|
|
195
|
+
* guessing:
|
|
196
|
+
*
|
|
197
|
+
* 1. Try a REAL refresh with the stored refresh token. If it succeeds the
|
|
198
|
+
* grant is alive (an independent `brigade login`, or a borrow the
|
|
199
|
+
* vendor still honours) — persist the rotated tokens and stop. An
|
|
200
|
+
* independent grant is never clobbered by adoption.
|
|
201
|
+
* 2. Only when the refresh is REJECTED (grant dead) adopt the machine's
|
|
202
|
+
* Claude Code CLI login — the same choice the operator made when they
|
|
203
|
+
* picked "reuse this machine's login" — and stamp the family link so
|
|
204
|
+
* the per-turn sync keeps it fresh from now on.
|
|
205
|
+
* 3. No CLI login to adopt → "none"; the auth error surfaces normally.
|
|
206
|
+
*
|
|
207
|
+
* Network I/O happens ONLY when the stored access token is already expired
|
|
208
|
+
* (a state that otherwise guarantees a failed turn). Concurrent calls for
|
|
209
|
+
* the same agent are coalesced. Best-effort: any failure returns "none".
|
|
210
|
+
*/
|
|
211
|
+
export async function healDeadSubscriptionLogin(agentId = DEFAULT_AGENT_ID, opts = {}) {
|
|
212
|
+
const inFlight = healInFlightByAgent.get(agentId);
|
|
213
|
+
if (inFlight)
|
|
214
|
+
return inFlight;
|
|
215
|
+
const run = healDeadSubscriptionLoginInner(agentId, opts).finally(() => {
|
|
216
|
+
healInFlightByAgent.delete(agentId);
|
|
217
|
+
});
|
|
218
|
+
healInFlightByAgent.set(agentId, run);
|
|
219
|
+
return run;
|
|
220
|
+
}
|
|
221
|
+
const healInFlightByAgent = new Map();
|
|
222
|
+
async function healDeadSubscriptionLoginInner(agentId, opts) {
|
|
223
|
+
try {
|
|
224
|
+
const now = opts.nowMs ?? Date.now();
|
|
225
|
+
const file = readProfiles(agentId);
|
|
226
|
+
const prof = Object.values(file.profiles ?? {}).find((p) => p?.provider === "anthropic" && p?.type === "oauth");
|
|
227
|
+
if (!prof)
|
|
228
|
+
return "none";
|
|
229
|
+
if (typeof prof.refresh !== "string" || prof.refresh.length === 0)
|
|
230
|
+
return "none";
|
|
231
|
+
// Only act on a PROVABLY expired (or about-to-expire) access token. A token
|
|
232
|
+
// still comfortably valid needs no help; a missing/zero expiry is left to
|
|
233
|
+
// Pi's normal refresh (acting on it would race Pi's own refresh). The 60s
|
|
234
|
+
// skew refreshes just BEFORE the boundary rather than just after.
|
|
235
|
+
const expires = typeof prof.expires === "number" && Number.isFinite(prof.expires) ? prof.expires : 0;
|
|
236
|
+
if (expires === 0 || expires > now + 60_000)
|
|
237
|
+
return "none";
|
|
238
|
+
const cli = (opts.cliRead ?? readClaudeCliLogin)();
|
|
239
|
+
const cliOauth = cli && cli.type === "oauth" && cli.access && cli.refresh ? cli : null;
|
|
240
|
+
// A linkable CLI login is the sync path's job — don't duplicate it here.
|
|
241
|
+
if (cliOauth && decideCliLoginAdoption(prof, cliOauth) !== "none")
|
|
242
|
+
return "none";
|
|
243
|
+
// 1) The stored grant may still be alive — a real refresh settles it.
|
|
244
|
+
const refreshed = await (opts.refreshFn ?? refreshAnthropicOAuthToken)(prof.refresh);
|
|
245
|
+
if (refreshed) {
|
|
246
|
+
updateOAuthTokens(agentId, "anthropic", {
|
|
247
|
+
access: refreshed.access,
|
|
248
|
+
refresh: refreshed.refresh,
|
|
249
|
+
expires: refreshed.expires,
|
|
250
|
+
});
|
|
251
|
+
return "refreshed";
|
|
252
|
+
}
|
|
253
|
+
// 2) Grant is dead. Adopt the machine's CLI login if it's usable.
|
|
254
|
+
const cliExpires = cliOauth && typeof cliOauth.expires === "number" && Number.isFinite(cliOauth.expires)
|
|
255
|
+
? cliOauth.expires
|
|
256
|
+
: 0;
|
|
257
|
+
if (cliOauth && cliExpires > expires) {
|
|
258
|
+
updateOAuthTokens(agentId, "anthropic", {
|
|
259
|
+
access: cliOauth.access,
|
|
260
|
+
refresh: cliOauth.refresh,
|
|
261
|
+
expires: cliOauth.expires,
|
|
262
|
+
metadata: { importedFrom: "claude-cli" },
|
|
263
|
+
});
|
|
264
|
+
return "adopted";
|
|
265
|
+
}
|
|
266
|
+
return "none";
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
return "none";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
/** Real OAuth refresh against the vendor token endpoint. Null on rejection
|
|
273
|
+
* (dead grant) OR network failure — the caller treats both as "not alive
|
|
274
|
+
* here"; a network blip then simply falls through to the adopt/none path. */
|
|
275
|
+
async function refreshAnthropicOAuthToken(refreshToken) {
|
|
276
|
+
try {
|
|
277
|
+
const res = await fetch(ANTHROPIC_OAUTH_TOKEN_URL, {
|
|
278
|
+
method: "POST",
|
|
279
|
+
headers: { "content-type": "application/json" },
|
|
280
|
+
body: JSON.stringify({
|
|
281
|
+
grant_type: "refresh_token",
|
|
282
|
+
client_id: CLAUDE_CODE_OAUTH_CLIENT_ID,
|
|
283
|
+
refresh_token: refreshToken,
|
|
284
|
+
}),
|
|
285
|
+
signal: AbortSignal.timeout(10_000),
|
|
286
|
+
});
|
|
287
|
+
if (!res.ok)
|
|
288
|
+
return null;
|
|
289
|
+
const data = (await res.json());
|
|
290
|
+
if (!data.access_token || !data.refresh_token)
|
|
291
|
+
return null;
|
|
292
|
+
const ttlMs = (typeof data.expires_in === "number" ? data.expires_in : 3600) * 1000;
|
|
293
|
+
// 5-minute early-expiry margin, mirroring the SDK's login flow.
|
|
294
|
+
return {
|
|
295
|
+
access: data.access_token,
|
|
296
|
+
refresh: data.refresh_token,
|
|
297
|
+
expires: Date.now() + ttlMs - 5 * 60_000,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
return null;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Pure decision core for `adoptNewerClaudeCliLogin` (unit-testable without
|
|
306
|
+
* storage or the CLI file):
|
|
307
|
+
* - "adopt" — same grant family and the CLI holds newer tokens.
|
|
308
|
+
* - "stamp" — same family, nothing newer, but the profile predates the
|
|
309
|
+
* `importedFrom` stamp; write the stamp so the link survives divergence.
|
|
310
|
+
* - "none" — different grant (independent `brigade login`) or already
|
|
311
|
+
* up to date and stamped.
|
|
312
|
+
*/
|
|
313
|
+
export function decideCliLoginAdoption(prof, cli) {
|
|
314
|
+
const stamped = prof.metadata?.importedFrom === "claude-cli";
|
|
315
|
+
const sameFamily = stamped ||
|
|
316
|
+
(typeof prof.access === "string" && prof.access.length > 0 && prof.access === cli.access) ||
|
|
317
|
+
(typeof prof.refresh === "string" && prof.refresh.length > 0 && prof.refresh === cli.refresh);
|
|
318
|
+
if (!sameFamily)
|
|
319
|
+
return "none";
|
|
320
|
+
const cliExpires = typeof cli.expires === "number" && Number.isFinite(cli.expires) ? cli.expires : 0;
|
|
321
|
+
const profExpires = typeof prof.expires === "number" && Number.isFinite(prof.expires) ? prof.expires : 0;
|
|
322
|
+
if (cliExpires <= profExpires)
|
|
323
|
+
return stamped ? "none" : "stamp";
|
|
324
|
+
return "adopt";
|
|
325
|
+
}
|
|
120
326
|
/** One-line-per-provider operator warning, or "" when healthy. */
|
|
121
327
|
export function formatUnrefreshableWarning(list) {
|
|
122
328
|
if (list.length === 0)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-health.js","sourceRoot":"","sources":["../../src/auth/auth-health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"auth-health.js","sourceRoot":"","sources":["../../src/auth/auth-health.ts"],"names":[],"mappings":"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"}
|
package/dist/buildstamp.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"builtAt":
|
|
1
|
+
{"builtAt":1783226076482,"head":"84aa6f14a66782ede47bacf097a362fb13348cd0","version":"1.24.0"}
|
|
@@ -121,6 +121,24 @@ async function runAuthLogin(provider) {
|
|
|
121
121
|
};
|
|
122
122
|
process.once("SIGINT", onSigint);
|
|
123
123
|
try {
|
|
124
|
+
// claude-cli backend — its own zero-key browser-login flow (installs the
|
|
125
|
+
// binary if needed, drives the OAuth, writes Brigade's managed grant). It's
|
|
126
|
+
// a noAuth provider so it can't go through the subscription/key path below.
|
|
127
|
+
const cliArg = provider?.trim().toLowerCase();
|
|
128
|
+
if (cliArg && ["claude-cli", "cli", "claude-code-cli", "claudecli"].includes(cliArg)) {
|
|
129
|
+
const { ensureClaudeCli } = await import("../../ui/onboarding.js");
|
|
130
|
+
const r = await ensureClaudeCli(tui, authStorage);
|
|
131
|
+
tui.stop();
|
|
132
|
+
restoreTerminal();
|
|
133
|
+
await flushAllPendingWrites();
|
|
134
|
+
if (r === "back") {
|
|
135
|
+
console.error(chalk.dim("Cancelled."));
|
|
136
|
+
return 0;
|
|
137
|
+
}
|
|
138
|
+
console.error(chalk.green("✓ Claude subscription connected (via the Claude Code CLI backend)."));
|
|
139
|
+
console.error(chalk.dim("Select it in chat with `/provider claude-cli`."));
|
|
140
|
+
return 0;
|
|
141
|
+
}
|
|
124
142
|
let info;
|
|
125
143
|
if (provider) {
|
|
126
144
|
const found = findProvider(provider);
|