@cortexkit/opencode-anthropic-auth 1.21.0 → 1.22.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.
@@ -1 +1 @@
1
- import{Fc as a,Gc as b,Hc as c,Ic as d,Jc as e,Kc as f,Lc as g,Mc as h,Nc as i,Oc as j,Pc as k,Qc as l,Rc as m}from"./index-4nz423bt.js";import"./index-4x20896x.js";export{d as shouldEmit,b as setLogLevel,m as relayLog,h as redactPayload,a as parseLogLevel,k as logger,l as log,g as isSecretKey,c as getLogLevel,e as getLogFilePath,i as formatLogLine,j as __setLogTestSink,f as SECRET_KEY_EXACT};
1
+ import{ad as a,bd as b,cd as c,dd as d,ed as e,fd as f,gd as g,hd as h,id as i,jd as j,kd as k,ld as l,md as m}from"./index-8aga2zwv.js";import"./index-cgez4m0h.js";export{d as shouldEmit,b as setLogLevel,m as relayLog,h as redactPayload,a as parseLogLevel,k as logger,l as log,g as isSecretKey,c as getLogLevel,e as getLogFilePath,i as formatLogLine,j as __setLogTestSink,f as SECRET_KEY_EXACT};
@@ -1 +1 @@
1
- import{Sc as a,Tc as b}from"../index-w9d41yy9.js";import"../index-4x20896x.js";export{a as writePortFile,b as discoverPortFile};
1
+ import{nd as a,od as b}from"../index-926t2bzc.js";import"../index-cgez4m0h.js";export{a as writePortFile,b as discoverPortFile};
@@ -1,5 +1,20 @@
1
1
  export declare const COMMAND_MODAL_NAMES: readonly ['claude-account', 'claude-cache', 'claude-cachekeep', 'claude-prime', 'claude-start', 'claude-quota', 'claude-dump', 'claude-fast', 'claude-routing', 'claude-killswitch', 'claude-logging'];
2
2
  export type CommandModalName = (typeof COMMAND_MODAL_NAMES)[number];
3
+ export interface AccountDialogAccount {
4
+ id: string;
5
+ label: string;
6
+ role: string;
7
+ enabled: boolean;
8
+ quotaPercent: number | null;
9
+ tierLabel?: string;
10
+ claustrumGate: 'on' | 'off' | 'na';
11
+ vaultServed: boolean;
12
+ }
13
+ export interface AccountDialogKnobs {
14
+ accounts: AccountDialogAccount[];
15
+ claustrumDetection: string;
16
+ [key: string]: unknown;
17
+ }
3
18
  export interface OpenDialogPayload {
4
19
  command: CommandModalName;
5
20
  text: string;
@@ -1 +1 @@
1
- import{Uc as a}from"../index-1db17bc2.js";import"../index-4x20896x.js";export{a as COMMAND_MODAL_NAMES};
1
+ import{pd as a}from"../index-bx5hsgf8.js";import"../index-cgez4m0h.js";export{a as COMMAND_MODAL_NAMES};
@@ -1 +1 @@
1
- import{Tc as l}from"../index-w9d41yy9.js";import"../index-4x20896x.js";async function a(n,e,t,o){let r=await l(n,o);if(!r)return null;let i=new AbortController,p=setTimeout(()=>i.abort(),2000);try{let s=await fetch(`http://127.0.0.1:${r.port}/rpc/${e}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.token}`},body:JSON.stringify(t),signal:i.signal});if(!s.ok)return null;return await s.json()}catch{return null}finally{clearTimeout(p)}}function u(n,e){return{async pending(t,o){return(await a(n,"pending-notifications",{lastReceivedId:t,sessionId:o},e))?.messages??[]},async apply(t){return await a(n,"apply",{...t},e)??{text:"apply failed",knobs:{}}}}}export{u as createRpcClient};
1
+ import{od as l}from"../index-926t2bzc.js";import"../index-cgez4m0h.js";async function a(n,e,t,o){let r=await l(n,o);if(!r)return null;let i=new AbortController,p=setTimeout(()=>i.abort(),2000);try{let s=await fetch(`http://127.0.0.1:${r.port}/rpc/${e}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.token}`},body:JSON.stringify(t),signal:i.signal});if(!s.ok)return null;return await s.json()}catch{return null}finally{clearTimeout(p)}}function u(n,e){return{async pending(t,o){return(await a(n,"pending-notifications",{lastReceivedId:t,sessionId:o},e))?.messages??[]},async apply(t){return await a(n,"apply",{...t},e)??{text:"apply failed",knobs:{}}}}}export{u as createRpcClient};
@@ -1 +1 @@
1
- import{Vc as a,Wc as b}from"../index-y0khnbt6.js";import"../index-4x20896x.js";export{a as tmpdir,b as getRpcDir};
1
+ import{qd as a,rd as b}from"../index-7f57ewkp.js";import"../index-cgez4m0h.js";export{a as tmpdir,b as getRpcDir};
@@ -37,6 +37,7 @@ export interface SidebarAccountState {
37
37
  quota: AccountQuota | null;
38
38
  enabled: boolean;
39
39
  needsReauth: boolean;
40
+ vaultReauth?: boolean;
40
41
  tierLabel?: string;
41
42
  }
42
43
  export interface FableRecoverySidebarState {
@@ -140,7 +141,7 @@ export declare function resolveActiveAccount(state: SidebarState): {
140
141
  };
141
142
  export declare function formatScopedQuotaLabel(title: string): string;
142
143
  /**
143
- * Pretty label for a recoverable-refusal source model (Fable 5 or Opus 5).
144
+ * Pretty label for a recoverable-refusal source model (Fable 5/5.1 or Opus 5).
144
145
  * Falls back to the raw id for unrecognized ids so the sidebar never goes
145
146
  * blank on a future model that has not yet been cataloged here.
146
147
  */
@@ -1 +1 @@
1
- import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}from"./index-wezdyxst.js";import"./index-yskwj5e6.js";import"./index-4nz423bt.js";import"./index-4x20896x.js";export{i as setSidebarState,k as resolveActiveAccount,c as normalizeSidebarState,a as getSidebarStateFile,h as getSidebarState,f as getInitialSidebarRoutingTestHooks,q as getFableRecoverySummary,r as getCollapsedQuotaSummary,l as formatScopedQuotaLabel,n as formatPrimeTime,o as formatPrimeCost,p as formatPrimeAccountValue,m as formatFallbackModelLabel,j as drainSidebarWrites,u as computeQuotaPacing,d as __setSidebarStateWriteTestHooks,e as __setInitialSidebarRoutingTestHooks,g as __acquireSidebarStateLockForTest,t as SEVEN_DAY_MS,s as FIVE_HOUR_MS,b as DEFAULT_SIDEBAR_STATE};
1
+ import{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u}from"./index-sh51yqxs.js";import"./index-d3f8g6ve.js";import"./index-8aga2zwv.js";import"./index-cgez4m0h.js";export{i as setSidebarState,k as resolveActiveAccount,c as normalizeSidebarState,a as getSidebarStateFile,h as getSidebarState,f as getInitialSidebarRoutingTestHooks,q as getFableRecoverySummary,r as getCollapsedQuotaSummary,l as formatScopedQuotaLabel,n as formatPrimeTime,o as formatPrimeCost,p as formatPrimeAccountValue,m as formatFallbackModelLabel,j as drainSidebarWrites,u as computeQuotaPacing,d as __setSidebarStateWriteTestHooks,e as __setInitialSidebarRoutingTestHooks,g as __acquireSidebarStateLockForTest,t as SEVEN_DAY_MS,s as FIVE_HOUR_MS,b as DEFAULT_SIDEBAR_STATE};
@@ -1,4 +1,4 @@
1
- import { type Cache1hMode, type ClaudeCodeIdentity } from '@cortexkit/anthropic-auth-core';
1
+ import { type Cache1hMode, type ClaudeCodeIdentity, type ThinkingPrefixMismatchBehavior } from '@cortexkit/anthropic-auth-core';
2
2
  import { type ServerSideFallbackOutcome } from './server-fallback';
3
3
  export declare const NON_STREAMING_DIAGNOSTICS_MAX_BYTES: number;
4
4
  export type FetchInput = string | URL | Request;
@@ -79,17 +79,28 @@ export declare function prepareFableCacheWarmSource(bodyText: string, fableModel
79
79
  * Rewrite the full request body: sanitize system prompt and prefix tool names.
80
80
  */
81
81
  type RewritePerfCallback = (stage: string, data?: Record<string, unknown>) => void;
82
+ export declare const CC_VERSION_SUFFIX_SESSION_LIMIT = 1000;
83
+ export declare function resetPinnedFirstUserTextsForTest(): void;
84
+ export declare function hasPinnedFirstUserTextForTest(sessionId: string): boolean;
82
85
  export declare function rewriteRequestBody(body: string, options?: {
83
86
  cache1hEnabled?: boolean;
84
87
  cache1hMode?: Cache1hMode;
85
88
  fastModeEnabled?: boolean;
86
89
  identity?: ClaudeCodeIdentity;
90
+ sessionId?: string;
91
+ thinkingPrefixMismatchBehavior?: ThinkingPrefixMismatchBehavior;
92
+ midConversationEffortEnabled?: boolean;
93
+ midConversationEffortPlan?: string;
87
94
  perf?: RewritePerfCallback;
88
95
  hybridStandbyAnchor?: HybridMessageCacheAnchor;
89
96
  serverSideFallbackEnabled?: boolean;
90
97
  laneStart?: boolean;
91
98
  cacheDiagnosticsPreviousMessageId?: string | null;
92
99
  }): Promise<string>;
100
+ type RelayUpstreamStatus = {
101
+ status: number;
102
+ source: 'relay_status_field' | 'relay_message_parse';
103
+ };
93
104
  /**
94
105
  * Create a streaming response that strips the tool prefix from tool names.
95
106
  */
@@ -108,6 +119,7 @@ export declare function createStrippedStream(response: Response, options?: {
108
119
  stopReason?: string;
109
120
  }) => void;
110
121
  onMessageResponse?: (message: Record<string, unknown>) => void;
122
+ onRelayUpstreamError?: (status: RelayUpstreamStatus) => void;
111
123
  onStreamEnd?: () => void | Promise<void>;
112
124
  responseMode?: 'json';
113
125
  laneStart?: boolean;
@@ -1,6 +1,7 @@
1
1
  /** @jsxImportSource @opentui/solid */
2
2
  import type { PrimeAccountStatus } from '@cortexkit/anthropic-auth-core';
3
3
  import type { TuiPluginApi } from '@opencode-ai/plugin/tui';
4
+ import type { AccountDialogAccount } from '../rpc/protocol';
4
5
  import type { OpenDialogPayload } from '../rpc/protocol.js';
5
6
  type ApplyFn = (command: OpenDialogPayload['command'], args: string) => Promise<{
6
7
  text: string;
@@ -19,14 +20,7 @@ export declare function handlePrimeStatusOption(option: {
19
20
  value: string;
20
21
  }, renderMain: () => void): void;
21
22
  export declare function buildKillswitchThresholdSeed(config: KillswitchDialogConfig, accountIds: string[]): string;
22
- export declare function buildAccountDialogOption(account: {
23
- id: string;
24
- label: string;
25
- role: string;
26
- enabled: boolean;
27
- quotaPercent: number | null;
28
- tierLabel?: string;
29
- }): {
23
+ export declare function buildAccountDialogOption(account: AccountDialogAccount): {
30
24
  title: string;
31
25
  value: string;
32
26
  description?: string | undefined;
@@ -1,4 +1,4 @@
1
- import{Xc as c,Yc as C,Zc as v}from"./index-4x20896x.js";var m=C((h,k)=>{(function(Q){if(typeof k==="object"&&typeof k.exports==="object"){var J=Q(v,h);if(J!==void 0)k.exports=J}else if(typeof define==="function"&&define.amd)define(["require","exports","./impl/format","./impl/edit","./impl/scanner","./impl/parser"],Q)})(function(Q,J){Object.defineProperty(J,"__esModule",{value:!0}),J.applyEdits=J.modify=J.format=J.printParseErrorCode=J.ParseErrorCode=J.stripComments=J.visit=J.getNodeValue=J.getNodePath=J.findNodeAtOffset=J.findNodeAtLocation=J.parseTree=J.parse=J.getLocation=J.SyntaxKind=J.ScanError=J.createScanner=void 0;let X=Q("./impl/format"),G=Q("./impl/edit"),Z=Q("./impl/scanner"),$=Q("./impl/parser");J.createScanner=Z.createScanner;var V;(function(z){z[z.None=0]="None",z[z.UnexpectedEndOfComment=1]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=2]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=3]="UnexpectedEndOfNumber",z[z.InvalidUnicode=4]="InvalidUnicode",z[z.InvalidEscapeCharacter=5]="InvalidEscapeCharacter",z[z.InvalidCharacter=6]="InvalidCharacter"})(V||(J.ScanError=V={}));var Y;(function(z){z[z.OpenBraceToken=1]="OpenBraceToken",z[z.CloseBraceToken=2]="CloseBraceToken",z[z.OpenBracketToken=3]="OpenBracketToken",z[z.CloseBracketToken=4]="CloseBracketToken",z[z.CommaToken=5]="CommaToken",z[z.ColonToken=6]="ColonToken",z[z.NullKeyword=7]="NullKeyword",z[z.TrueKeyword=8]="TrueKeyword",z[z.FalseKeyword=9]="FalseKeyword",z[z.StringLiteral=10]="StringLiteral",z[z.NumericLiteral=11]="NumericLiteral",z[z.LineCommentTrivia=12]="LineCommentTrivia",z[z.BlockCommentTrivia=13]="BlockCommentTrivia",z[z.LineBreakTrivia=14]="LineBreakTrivia",z[z.Trivia=15]="Trivia",z[z.Unknown=16]="Unknown",z[z.EOF=17]="EOF"})(Y||(J.SyntaxKind=Y={})),J.getLocation=$.getLocation,J.parse=$.parse,J.parseTree=$.parseTree,J.findNodeAtLocation=$.findNodeAtLocation,J.findNodeAtOffset=$.findNodeAtOffset,J.getNodePath=$.getNodePath,J.getNodeValue=$.getNodeValue,J.visit=$.visit,J.stripComments=$.stripComments;var A;(function(z){z[z.InvalidSymbol=1]="InvalidSymbol",z[z.InvalidNumberFormat=2]="InvalidNumberFormat",z[z.PropertyNameExpected=3]="PropertyNameExpected",z[z.ValueExpected=4]="ValueExpected",z[z.ColonExpected=5]="ColonExpected",z[z.CommaExpected=6]="CommaExpected",z[z.CloseBraceExpected=7]="CloseBraceExpected",z[z.CloseBracketExpected=8]="CloseBracketExpected",z[z.EndOfFileExpected=9]="EndOfFileExpected",z[z.InvalidCommentToken=10]="InvalidCommentToken",z[z.UnexpectedEndOfComment=11]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=12]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=13]="UnexpectedEndOfNumber",z[z.InvalidUnicode=14]="InvalidUnicode",z[z.InvalidEscapeCharacter=15]="InvalidEscapeCharacter",z[z.InvalidCharacter=16]="InvalidCharacter"})(A||(J.ParseErrorCode=A={}));function L(z){switch(z){case 1:return"InvalidSymbol";case 2:return"InvalidNumberFormat";case 3:return"PropertyNameExpected";case 4:return"ValueExpected";case 5:return"ColonExpected";case 6:return"CommaExpected";case 7:return"CloseBraceExpected";case 8:return"CloseBracketExpected";case 9:return"EndOfFileExpected";case 10:return"InvalidCommentToken";case 11:return"UnexpectedEndOfComment";case 12:return"UnexpectedEndOfString";case 13:return"UnexpectedEndOfNumber";case 14:return"InvalidUnicode";case 15:return"InvalidEscapeCharacter";case 16:return"InvalidCharacter"}return"<unknown ParseErrorCode>"}J.printParseErrorCode=L;function W(z,B,j){return X.format(z,B,j)}J.format=W;function q(z,B,j,R){return G.setProperty(z,B,j,R)}J.modify=q;function O(z,B){let j=B.slice(0).sort((M,N)=>{let T=M.offset-N.offset;if(T===0)return M.length-N.length;return T}),R=z.length;for(let M=j.length-1;M>=0;M--){let N=j[M];if(N.offset+N.length<=R)z=G.applyEdit(z,N);else throw Error("Overlapping edit");R=N.offset}return z}J.applyEdits=O})});var I=c(m(),1);import{readFileSync as y,watch as S}from"node:fs";import{mkdir as E,readFile as g,rename as p,writeFile as l}from"node:fs/promises";import{homedir as x}from"node:os";import{basename as i,dirname as P,join as w}from"node:path";import{clearTimeout as _,setTimeout as f}from"node:timers";var s="OPENCODE_TUI_PREFERENCES_FILE",d="tui-preferences.jsonc";function b(){let Q=process.env[s];if(Q)return Q;let J=process.env.OPENCODE_CONFIG_DIR||w(process.env.XDG_CONFIG_HOME||w(x(),".config"),"opencode");return w(J,d)}function U(Q){return typeof Q==="object"&&Q!==null&&!Array.isArray(Q)}async function Yz(){try{let Q=await g(b(),"utf8"),J=[],X=I.parse(Q,J,{allowTrailingComma:!0});if(J.length>0)return{};return U(X)?X:{}}catch{return{}}}var n="anthropic-auth",t=160,u={forceToTop:!1,order:t,startCollapsed:!1,rememberCollapsed:!0,collapsed:null,pollMs:1500,refreshDebounceMs:200,header:{label:"CLAUDE",showVersion:!0},sections:{quota:!0,fallbackAccounts:!0,routing:!0,cache:!0,health:!0,pacing:!0},appearance:{barWidth:10,barFilledChar:"█",barEmptyChar:"░",warnThreshold:50,errorThreshold:80}};function H(Q,J){return typeof Q==="boolean"?Q:J}function D(Q,J,X,G){if(typeof Q!=="number"||!Number.isFinite(Q))return J;return Math.min(Math.max(Math.round(Q),X),G)}function a(Q,J,X){if(typeof Q!=="string"||Q.length===0)return J;return Q.slice(0,X)}function K(Q,J){if(typeof Q!=="string")return J;return[...Q][0]??J}function Bz(Q){let J=Q[n];if(!U(J))return structuredClone(u);let X=u,G=U(J.header)?J.header:{},Z=U(J.sections)?J.sections:{},$=U(J.appearance)?J.appearance:{},V=D($.warnThreshold,X.appearance.warnThreshold,0,99),Y=Math.max(D($.errorThreshold,X.appearance.errorThreshold,0,100),Math.min(V+1,100));return{forceToTop:H(J.forceToTop,X.forceToTop),order:D(J.order,X.order,-1e4,1e4),startCollapsed:H(J.startCollapsed,X.startCollapsed),rememberCollapsed:H(J.rememberCollapsed,X.rememberCollapsed),collapsed:typeof J.collapsed==="boolean"?J.collapsed:null,pollMs:D(J.pollMs,X.pollMs,500,30000),refreshDebounceMs:D(J.refreshDebounceMs,X.refreshDebounceMs,50,5000),header:{label:a(G.label,X.header.label,20),showVersion:H(G.showVersion,X.header.showVersion)},sections:{quota:H(Z.quota,X.sections.quota),fallbackAccounts:H(Z.fallbackAccounts,X.sections.fallbackAccounts),routing:H(Z.routing,X.sections.routing),cache:H(Z.cache,X.sections.cache),health:H(Z.health,X.sections.health),pacing:H(Z.pacing,X.sections.pacing)},appearance:{barWidth:D($.barWidth,X.appearance.barWidth,4,40),barFilledChar:K($.barFilledChar,X.appearance.barFilledChar),barEmptyChar:K($.barEmptyChar,X.appearance.barEmptyChar),warnThreshold:V,errorThreshold:Y}}}var o=-1e5;function Hz(Q,J,X){let G=Q[J];if(!U(G))return X;if(G.forceToTop===!0)return o+Object.keys(Q).indexOf(J);return D(G.order,X,-1e4,1e4)}var e=`// Shared preferences for opencode TUI plugins.
1
+ import{sd as c,td as C,ud as v}from"./index-cgez4m0h.js";var m=C((h,k)=>{(function(Q){if(typeof k==="object"&&typeof k.exports==="object"){var J=Q(v,h);if(J!==void 0)k.exports=J}else if(typeof define==="function"&&define.amd)define(["require","exports","./impl/format","./impl/edit","./impl/scanner","./impl/parser"],Q)})(function(Q,J){Object.defineProperty(J,"__esModule",{value:!0}),J.applyEdits=J.modify=J.format=J.printParseErrorCode=J.ParseErrorCode=J.stripComments=J.visit=J.getNodeValue=J.getNodePath=J.findNodeAtOffset=J.findNodeAtLocation=J.parseTree=J.parse=J.getLocation=J.SyntaxKind=J.ScanError=J.createScanner=void 0;let X=Q("./impl/format"),G=Q("./impl/edit"),Z=Q("./impl/scanner"),$=Q("./impl/parser");J.createScanner=Z.createScanner;var V;(function(z){z[z.None=0]="None",z[z.UnexpectedEndOfComment=1]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=2]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=3]="UnexpectedEndOfNumber",z[z.InvalidUnicode=4]="InvalidUnicode",z[z.InvalidEscapeCharacter=5]="InvalidEscapeCharacter",z[z.InvalidCharacter=6]="InvalidCharacter"})(V||(J.ScanError=V={}));var Y;(function(z){z[z.OpenBraceToken=1]="OpenBraceToken",z[z.CloseBraceToken=2]="CloseBraceToken",z[z.OpenBracketToken=3]="OpenBracketToken",z[z.CloseBracketToken=4]="CloseBracketToken",z[z.CommaToken=5]="CommaToken",z[z.ColonToken=6]="ColonToken",z[z.NullKeyword=7]="NullKeyword",z[z.TrueKeyword=8]="TrueKeyword",z[z.FalseKeyword=9]="FalseKeyword",z[z.StringLiteral=10]="StringLiteral",z[z.NumericLiteral=11]="NumericLiteral",z[z.LineCommentTrivia=12]="LineCommentTrivia",z[z.BlockCommentTrivia=13]="BlockCommentTrivia",z[z.LineBreakTrivia=14]="LineBreakTrivia",z[z.Trivia=15]="Trivia",z[z.Unknown=16]="Unknown",z[z.EOF=17]="EOF"})(Y||(J.SyntaxKind=Y={})),J.getLocation=$.getLocation,J.parse=$.parse,J.parseTree=$.parseTree,J.findNodeAtLocation=$.findNodeAtLocation,J.findNodeAtOffset=$.findNodeAtOffset,J.getNodePath=$.getNodePath,J.getNodeValue=$.getNodeValue,J.visit=$.visit,J.stripComments=$.stripComments;var A;(function(z){z[z.InvalidSymbol=1]="InvalidSymbol",z[z.InvalidNumberFormat=2]="InvalidNumberFormat",z[z.PropertyNameExpected=3]="PropertyNameExpected",z[z.ValueExpected=4]="ValueExpected",z[z.ColonExpected=5]="ColonExpected",z[z.CommaExpected=6]="CommaExpected",z[z.CloseBraceExpected=7]="CloseBraceExpected",z[z.CloseBracketExpected=8]="CloseBracketExpected",z[z.EndOfFileExpected=9]="EndOfFileExpected",z[z.InvalidCommentToken=10]="InvalidCommentToken",z[z.UnexpectedEndOfComment=11]="UnexpectedEndOfComment",z[z.UnexpectedEndOfString=12]="UnexpectedEndOfString",z[z.UnexpectedEndOfNumber=13]="UnexpectedEndOfNumber",z[z.InvalidUnicode=14]="InvalidUnicode",z[z.InvalidEscapeCharacter=15]="InvalidEscapeCharacter",z[z.InvalidCharacter=16]="InvalidCharacter"})(A||(J.ParseErrorCode=A={}));function L(z){switch(z){case 1:return"InvalidSymbol";case 2:return"InvalidNumberFormat";case 3:return"PropertyNameExpected";case 4:return"ValueExpected";case 5:return"ColonExpected";case 6:return"CommaExpected";case 7:return"CloseBraceExpected";case 8:return"CloseBracketExpected";case 9:return"EndOfFileExpected";case 10:return"InvalidCommentToken";case 11:return"UnexpectedEndOfComment";case 12:return"UnexpectedEndOfString";case 13:return"UnexpectedEndOfNumber";case 14:return"InvalidUnicode";case 15:return"InvalidEscapeCharacter";case 16:return"InvalidCharacter"}return"<unknown ParseErrorCode>"}J.printParseErrorCode=L;function W(z,B,j){return X.format(z,B,j)}J.format=W;function q(z,B,j,R){return G.setProperty(z,B,j,R)}J.modify=q;function O(z,B){let j=B.slice(0).sort((M,N)=>{let T=M.offset-N.offset;if(T===0)return M.length-N.length;return T}),R=z.length;for(let M=j.length-1;M>=0;M--){let N=j[M];if(N.offset+N.length<=R)z=G.applyEdit(z,N);else throw Error("Overlapping edit");R=N.offset}return z}J.applyEdits=O})});var I=c(m(),1);import{readFileSync as y,watch as S}from"node:fs";import{mkdir as E,readFile as g,rename as p,writeFile as l}from"node:fs/promises";import{homedir as x}from"node:os";import{basename as i,dirname as P,join as w}from"node:path";import{clearTimeout as _,setTimeout as f}from"node:timers";var s="OPENCODE_TUI_PREFERENCES_FILE",d="tui-preferences.jsonc";function b(){let Q=process.env[s];if(Q)return Q;let J=process.env.OPENCODE_CONFIG_DIR||w(process.env.XDG_CONFIG_HOME||w(x(),".config"),"opencode");return w(J,d)}function U(Q){return typeof Q==="object"&&Q!==null&&!Array.isArray(Q)}async function Yz(){try{let Q=await g(b(),"utf8"),J=[],X=I.parse(Q,J,{allowTrailingComma:!0});if(J.length>0)return{};return U(X)?X:{}}catch{return{}}}var n="anthropic-auth",t=160,u={forceToTop:!1,order:t,startCollapsed:!1,rememberCollapsed:!0,collapsed:null,pollMs:1500,refreshDebounceMs:200,header:{label:"CLAUDE",showVersion:!0},sections:{quota:!0,fallbackAccounts:!0,routing:!0,cache:!0,health:!0,pacing:!0},appearance:{barWidth:10,barFilledChar:"█",barEmptyChar:"░",warnThreshold:50,errorThreshold:80}};function H(Q,J){return typeof Q==="boolean"?Q:J}function D(Q,J,X,G){if(typeof Q!=="number"||!Number.isFinite(Q))return J;return Math.min(Math.max(Math.round(Q),X),G)}function a(Q,J,X){if(typeof Q!=="string"||Q.length===0)return J;return Q.slice(0,X)}function K(Q,J){if(typeof Q!=="string")return J;return[...Q][0]??J}function Bz(Q){let J=Q[n];if(!U(J))return structuredClone(u);let X=u,G=U(J.header)?J.header:{},Z=U(J.sections)?J.sections:{},$=U(J.appearance)?J.appearance:{},V=D($.warnThreshold,X.appearance.warnThreshold,0,99),Y=Math.max(D($.errorThreshold,X.appearance.errorThreshold,0,100),Math.min(V+1,100));return{forceToTop:H(J.forceToTop,X.forceToTop),order:D(J.order,X.order,-1e4,1e4),startCollapsed:H(J.startCollapsed,X.startCollapsed),rememberCollapsed:H(J.rememberCollapsed,X.rememberCollapsed),collapsed:typeof J.collapsed==="boolean"?J.collapsed:null,pollMs:D(J.pollMs,X.pollMs,500,30000),refreshDebounceMs:D(J.refreshDebounceMs,X.refreshDebounceMs,50,5000),header:{label:a(G.label,X.header.label,20),showVersion:H(G.showVersion,X.header.showVersion)},sections:{quota:H(Z.quota,X.sections.quota),fallbackAccounts:H(Z.fallbackAccounts,X.sections.fallbackAccounts),routing:H(Z.routing,X.sections.routing),cache:H(Z.cache,X.sections.cache),health:H(Z.health,X.sections.health),pacing:H(Z.pacing,X.sections.pacing)},appearance:{barWidth:D($.barWidth,X.appearance.barWidth,4,40),barFilledChar:K($.barFilledChar,X.appearance.barFilledChar),barEmptyChar:K($.barEmptyChar,X.appearance.barEmptyChar),warnThreshold:V,errorThreshold:Y}}}var o=-1e5;function Hz(Q,J,X){let G=Q[J];if(!U(G))return X;if(G.forceToTop===!0)return o+Object.keys(Q).indexOf(J);return D(G.order,X,-1e4,1e4)}var e=`// Shared preferences for opencode TUI plugins.
2
2
  // One top-level key per plugin (short name). See each plugin's README for
3
3
  // its supported settings. This file is safe to hand-edit; plugins update
4
4
  // individual keys in place and preserve comments.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-anthropic-auth",
3
- "version": "1.21.0",
3
+ "version": "1.22.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -61,7 +61,7 @@
61
61
  "@opencode-ai/plugin": "*"
62
62
  },
63
63
  "dependencies": {
64
- "@cortexkit/anthropic-auth-core": "1.21.0",
64
+ "@cortexkit/anthropic-auth-core": "1.22.0",
65
65
  "@opentui/core": "0.5.7",
66
66
  "@opentui/solid": "0.5.7",
67
67
  "jsonc-parser": "^3.3.1",
@@ -14,6 +14,23 @@ export const COMMAND_MODAL_NAMES = [
14
14
 
15
15
  export type CommandModalName = (typeof COMMAND_MODAL_NAMES)[number]
16
16
 
17
+ export interface AccountDialogAccount {
18
+ id: string
19
+ label: string
20
+ role: string
21
+ enabled: boolean
22
+ quotaPercent: number | null
23
+ tierLabel?: string
24
+ claustrumGate: 'on' | 'off' | 'na'
25
+ vaultServed: boolean
26
+ }
27
+
28
+ export interface AccountDialogKnobs {
29
+ accounts: AccountDialogAccount[]
30
+ claustrumDetection: string
31
+ [key: string]: unknown
32
+ }
33
+
17
34
  export interface OpenDialogPayload {
18
35
  command: CommandModalName
19
36
  text: string
@@ -34,6 +34,8 @@ export interface SidebarAccountState {
34
34
  // True when the account's refresh token is permanently dead (400
35
35
  // invalid_grant) and it needs a re-login — distinct from a transient backoff.
36
36
  needsReauth: boolean
37
+ // True when the vault copy needs re-importing while the sidecar remains usable.
38
+ vaultReauth?: boolean
37
39
  tierLabel?: string
38
40
  }
39
41
 
@@ -335,6 +337,7 @@ export function normalizeSidebarState(raw: unknown): SidebarState {
335
337
  enabled: typeof entry.enabled === 'boolean' ? entry.enabled : false,
336
338
  needsReauth:
337
339
  typeof entry.needsReauth === 'boolean' ? entry.needsReauth : false,
340
+ ...(entry.vaultReauth === true && { vaultReauth: true }),
338
341
  tierLabel:
339
342
  typeof entry.tierLabel === 'string' && entry.tierLabel.trim()
340
343
  ? entry.tierLabel.trim()
@@ -715,6 +718,8 @@ export async function setSidebarState(
715
718
  lastUpdated: Math.max(current.lastUpdated, state.lastUpdated),
716
719
  }
717
720
  }
721
+ // The state file is a cross-process artifact; future account fields must fail closed.
722
+ stateToWrite = normalizeSidebarState(stateToWrite)
718
723
  result = await writeSidebarStateAtomic(
719
724
  stateFile,
720
725
  stateToWrite,
@@ -795,11 +800,21 @@ export function formatScopedQuotaLabel(title: string) {
795
800
  }
796
801
 
797
802
  /**
798
- * Pretty label for a recoverable-refusal source model (Fable 5 or Opus 5).
803
+ * Pretty label for a recoverable-refusal source model (Fable 5/5.1 or Opus 5).
799
804
  * Falls back to the raw id for unrecognized ids so the sidebar never goes
800
805
  * blank on a future model that has not yet been cataloged here.
801
806
  */
802
807
  export function formatFallbackModelLabel(modelId: string | undefined): string {
808
+ if (
809
+ modelId === 'claude-mythos-5-1' ||
810
+ modelId?.startsWith('claude-mythos-5-1-')
811
+ )
812
+ return 'Mythos 5.1'
813
+ if (
814
+ modelId === 'claude-fable-5-1' ||
815
+ modelId?.startsWith('claude-fable-5-1-')
816
+ )
817
+ return 'Fable 5.1'
803
818
  if (modelId === 'claude-fable-5' || modelId?.startsWith('claude-fable-5-'))
804
819
  return 'Fable 5'
805
820
  if (modelId === 'claude-opus-5' || modelId?.startsWith('claude-opus-5-'))
@@ -1,6 +1,7 @@
1
1
  /** @jsxImportSource @opentui/solid */
2
2
  import type { PrimeAccountStatus } from '@cortexkit/anthropic-auth-core'
3
3
  import type { TuiPluginApi } from '@opencode-ai/plugin/tui'
4
+ import type { AccountDialogAccount } from '../rpc/protocol'
4
5
  import type { OpenDialogPayload } from '../rpc/protocol.js'
5
6
  import { formatPrimeCost, formatPrimeTime } from '../sidebar-state.js'
6
7
 
@@ -48,21 +49,19 @@ export function buildKillswitchThresholdSeed(
48
49
  return seedParts.join(' ')
49
50
  }
50
51
 
51
- export function buildAccountDialogOption(account: {
52
- id: string
53
- label: string
54
- role: string
55
- enabled: boolean
56
- quotaPercent: number | null
57
- tierLabel?: string
58
- }) {
52
+ export function buildAccountDialogOption(account: AccountDialogAccount) {
59
53
  const pct =
60
54
  account.quotaPercent != null
61
55
  ? ` ${Math.round(account.quotaPercent)}%`
62
56
  : ' \u2013%'
63
57
  const status = !account.enabled ? ' (disabled)' : ''
58
+ const gate = ` · gate ${account.claustrumGate === 'na' ? 'n/a' : account.claustrumGate}`
59
+ const vault =
60
+ account.role === 'main'
61
+ ? ' · vault n/a'
62
+ : ` · vault ${account.vaultServed ? 'served' : 'cold'}`
64
63
  return {
65
- title: `${account.label} [${account.role}]${status}${pct}`,
64
+ title: `${account.label} [${account.role}]${status}${pct}${gate}${vault}`,
66
65
  value: account.id,
67
66
  ...(account.tierLabel && { description: account.tierLabel }),
68
67
  }
@@ -379,14 +378,9 @@ export function openCommandDialog(
379
378
 
380
379
  if (payload.command === 'claude-account') {
381
380
  const accounts =
382
- (payload.knobs.accounts as Array<{
383
- id: string
384
- label: string
385
- role: string
386
- enabled: boolean
387
- quotaPercent: number | null
388
- tierLabel?: string
389
- }>) ?? []
381
+ (payload.knobs.accounts as AccountDialogAccount[] | undefined) ?? []
382
+ const claustrumDetection =
383
+ (payload.knobs.claustrumDetection as string | undefined) ?? 'unknown'
390
384
 
391
385
  const updateAccounts = (r: {
392
386
  text: string
@@ -415,30 +409,35 @@ export function openCommandDialog(
415
409
  ]
416
410
  api.ui.dialog.setSize('xlarge')
417
411
  api.ui.dialog.replace(() => (
418
- <DialogSelect
419
- title='Claude accounts'
420
- options={l1Options}
421
- onSelect={(option) => {
422
- if (option.value === '__add__') {
423
- openAddType()
424
- return
425
- }
426
- const account = accounts.find((a) => a.id === option.value)
427
- if (!account) return
428
- if (account.role === 'main') {
429
- const pct =
430
- account.quotaPercent != null
431
- ? ` ${Math.round(account.quotaPercent)}%`
432
- : ' \u2013%'
433
- showText(
434
- api,
435
- `${account.label}\nRole: main (read-only)\nQuota:${pct}`,
436
- )
437
- return
438
- }
439
- openManage(account, false)
440
- }}
441
- />
412
+ <box flexDirection='column' padding={1} width='100%'>
413
+ <text>{`Claustrum: ${claustrumDetection}`}</text>
414
+ <box marginTop={1}>
415
+ <DialogSelect
416
+ title='Claude accounts'
417
+ options={l1Options}
418
+ onSelect={(option) => {
419
+ if (option.value === '__add__') {
420
+ openAddType()
421
+ return
422
+ }
423
+ const account = accounts.find((a) => a.id === option.value)
424
+ if (!account) return
425
+ if (account.role === 'main') {
426
+ const pct =
427
+ account.quotaPercent != null
428
+ ? ` ${Math.round(account.quotaPercent)}%`
429
+ : ' \u2013%'
430
+ showText(
431
+ api,
432
+ `${account.label}\nRole: main (read-only)\nQuota:${pct}`,
433
+ )
434
+ return
435
+ }
436
+ openManage(account, false)
437
+ }}
438
+ />
439
+ </box>
440
+ </box>
442
441
  ))
443
442
  }
444
443
 
@@ -14,6 +14,23 @@ export const COMMAND_MODAL_NAMES = [
14
14
 
15
15
  export type CommandModalName = (typeof COMMAND_MODAL_NAMES)[number]
16
16
 
17
+ export interface AccountDialogAccount {
18
+ id: string
19
+ label: string
20
+ role: string
21
+ enabled: boolean
22
+ quotaPercent: number | null
23
+ tierLabel?: string
24
+ claustrumGate: 'on' | 'off' | 'na'
25
+ vaultServed: boolean
26
+ }
27
+
28
+ export interface AccountDialogKnobs {
29
+ accounts: AccountDialogAccount[]
30
+ claustrumDetection: string
31
+ [key: string]: unknown
32
+ }
33
+
17
34
  export interface OpenDialogPayload {
18
35
  command: CommandModalName
19
36
  text: string
@@ -34,6 +34,8 @@ export interface SidebarAccountState {
34
34
  // True when the account's refresh token is permanently dead (400
35
35
  // invalid_grant) and it needs a re-login — distinct from a transient backoff.
36
36
  needsReauth: boolean
37
+ // True when the vault copy needs re-importing while the sidecar remains usable.
38
+ vaultReauth?: boolean
37
39
  tierLabel?: string
38
40
  }
39
41
 
@@ -335,6 +337,7 @@ export function normalizeSidebarState(raw: unknown): SidebarState {
335
337
  enabled: typeof entry.enabled === 'boolean' ? entry.enabled : false,
336
338
  needsReauth:
337
339
  typeof entry.needsReauth === 'boolean' ? entry.needsReauth : false,
340
+ ...(entry.vaultReauth === true && { vaultReauth: true }),
338
341
  tierLabel:
339
342
  typeof entry.tierLabel === 'string' && entry.tierLabel.trim()
340
343
  ? entry.tierLabel.trim()
@@ -715,6 +718,8 @@ export async function setSidebarState(
715
718
  lastUpdated: Math.max(current.lastUpdated, state.lastUpdated),
716
719
  }
717
720
  }
721
+ // The state file is a cross-process artifact; future account fields must fail closed.
722
+ stateToWrite = normalizeSidebarState(stateToWrite)
718
723
  result = await writeSidebarStateAtomic(
719
724
  stateFile,
720
725
  stateToWrite,
@@ -795,11 +800,21 @@ export function formatScopedQuotaLabel(title: string) {
795
800
  }
796
801
 
797
802
  /**
798
- * Pretty label for a recoverable-refusal source model (Fable 5 or Opus 5).
803
+ * Pretty label for a recoverable-refusal source model (Fable 5/5.1 or Opus 5).
799
804
  * Falls back to the raw id for unrecognized ids so the sidebar never goes
800
805
  * blank on a future model that has not yet been cataloged here.
801
806
  */
802
807
  export function formatFallbackModelLabel(modelId: string | undefined): string {
808
+ if (
809
+ modelId === 'claude-mythos-5-1' ||
810
+ modelId?.startsWith('claude-mythos-5-1-')
811
+ )
812
+ return 'Mythos 5.1'
813
+ if (
814
+ modelId === 'claude-fable-5-1' ||
815
+ modelId?.startsWith('claude-fable-5-1-')
816
+ )
817
+ return 'Fable 5.1'
803
818
  if (modelId === 'claude-fable-5' || modelId?.startsWith('claude-fable-5-'))
804
819
  return 'Fable 5'
805
820
  if (modelId === 'claude-opus-5' || modelId?.startsWith('claude-opus-5-'))
@@ -45,8 +45,10 @@ export function buildKillswitchThresholdSeed(config, accountIds) {
45
45
  export function buildAccountDialogOption(account) {
46
46
  const pct = account.quotaPercent != null ? ` ${Math.round(account.quotaPercent)}%` : ' \u2013%';
47
47
  const status = !account.enabled ? ' (disabled)' : '';
48
+ const gate = ` · gate ${account.claustrumGate === 'na' ? 'n/a' : account.claustrumGate}`;
49
+ const vault = account.role === 'main' ? ' · vault n/a' : ` · vault ${account.vaultServed ? 'served' : 'cold'}`;
48
50
  return {
49
- title: `${account.label} [${account.role}]${status}${pct}`,
51
+ title: `${account.label} [${account.role}]${status}${pct}${gate}${vault}`,
50
52
  value: account.id,
51
53
  ...(account.tierLabel && {
52
54
  description: account.tierLabel
@@ -353,6 +355,7 @@ export function openCommandDialog(api, payload, apply) {
353
355
  }
354
356
  if (payload.command === 'claude-account') {
355
357
  const accounts = payload.knobs.accounts ?? [];
358
+ const claustrumDetection = payload.knobs.claustrumDetection ?? 'unknown';
356
359
  const updateAccounts = r => {
357
360
  const updated = r.knobs.accounts;
358
361
  if (updated && updated.length > 0) {
@@ -368,24 +371,37 @@ export function openCommandDialog(api, payload, apply) {
368
371
  description: 'Add an API key or OAuth fallback account'
369
372
  }, ...accounts.map(buildAccountDialogOption)];
370
373
  api.ui.dialog.setSize('xlarge');
371
- api.ui.dialog.replace(() => _$createComponent(DialogSelect, {
372
- title: "Claude accounts",
373
- options: l1Options,
374
- onSelect: option => {
375
- if (option.value === '__add__') {
376
- openAddType();
377
- return;
378
- }
379
- const account = accounts.find(a => a.id === option.value);
380
- if (!account) return;
381
- if (account.role === 'main') {
382
- const pct = account.quotaPercent != null ? ` ${Math.round(account.quotaPercent)}%` : ' \u2013%';
383
- showText(api, `${account.label}\nRole: main (read-only)\nQuota:${pct}`);
384
- return;
374
+ api.ui.dialog.replace(() => (() => {
375
+ var _el$8 = _$createElement("box"),
376
+ _el$9 = _$createElement("text"),
377
+ _el$0 = _$createElement("box");
378
+ _$insertNode(_el$8, _el$9);
379
+ _$insertNode(_el$8, _el$0);
380
+ _$setProp(_el$8, "flexDirection", 'column');
381
+ _$setProp(_el$8, "padding", 1);
382
+ _$setProp(_el$8, "width", '100%');
383
+ _$insert(_el$9, `Claustrum: ${claustrumDetection}`);
384
+ _$setProp(_el$0, "marginTop", 1);
385
+ _$insert(_el$0, _$createComponent(DialogSelect, {
386
+ title: "Claude accounts",
387
+ options: l1Options,
388
+ onSelect: option => {
389
+ if (option.value === '__add__') {
390
+ openAddType();
391
+ return;
392
+ }
393
+ const account = accounts.find(a => a.id === option.value);
394
+ if (!account) return;
395
+ if (account.role === 'main') {
396
+ const pct = account.quotaPercent != null ? ` ${Math.round(account.quotaPercent)}%` : ' \u2013%';
397
+ showText(api, `${account.label}\nRole: main (read-only)\nQuota:${pct}`);
398
+ return;
399
+ }
400
+ openManage(account, false);
385
401
  }
386
- openManage(account, false);
387
- }
388
- }));
402
+ }));
403
+ return _el$8;
404
+ })());
389
405
  };
390
406
 
391
407
  // -- Add type selection (OAuth vs API key) ------------------------------
@@ -429,9 +445,9 @@ export function openCommandDialog(api, payload, apply) {
429
445
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
430
446
  title: "Add API key account \\u2014 API key",
431
447
  description: () => (() => {
432
- var _el$8 = _$createElement("text");
433
- _$insertNode(_el$8, _$createTextNode(`Paste your API key (required).`));
434
- return _el$8;
448
+ var _el$1 = _$createElement("text");
449
+ _$insertNode(_el$1, _$createTextNode(`Paste your API key (required).`));
450
+ return _el$1;
435
451
  })(),
436
452
  placeholder: "sk-ant-...",
437
453
  value: "",
@@ -453,9 +469,9 @@ export function openCommandDialog(api, payload, apply) {
453
469
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
454
470
  title: "Add API key account \\u2014 base URL",
455
471
  description: () => (() => {
456
- var _el$0 = _$createElement("text");
457
- _$insertNode(_el$0, _$createTextNode(`Anthropic-compatible API base URL. Default: https://api.kie.ai/claude`));
458
- return _el$0;
472
+ var _el$11 = _$createElement("text");
473
+ _$insertNode(_el$11, _$createTextNode(`Anthropic-compatible API base URL. Default: https://api.kie.ai/claude`));
474
+ return _el$11;
459
475
  })(),
460
476
  placeholder: "https://api.kie.ai/claude",
461
477
  value: "",
@@ -493,9 +509,9 @@ export function openCommandDialog(api, payload, apply) {
493
509
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
494
510
  title: "Add API key account \\u2014 label",
495
511
  description: () => (() => {
496
- var _el$10 = _$createElement("text");
497
- _$insertNode(_el$10, _$createTextNode(`A short name for this account (optional).`));
498
- return _el$10;
512
+ var _el$13 = _$createElement("text");
513
+ _$insertNode(_el$13, _$createTextNode(`A short name for this account (optional).`));
514
+ return _el$13;
499
515
  })(),
500
516
  placeholder: "e.g. Work API",
501
517
  value: "",
@@ -589,9 +605,9 @@ export function openCommandDialog(api, payload, apply) {
589
605
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
590
606
  title: "OAuth sign-in \\u2014 enter code",
591
607
  description: () => (() => {
592
- var _el$12 = _$createElement("text");
593
- _$insertNode(_el$12, _$createTextNode(`After signing in you will be redirected. Paste the full callback URL or authorization code below.`));
594
- return _el$12;
608
+ var _el$15 = _$createElement("text");
609
+ _$insertNode(_el$15, _$createTextNode(`After signing in you will be redirected. Paste the full callback URL or authorization code below.`));
610
+ return _el$15;
595
611
  })(),
596
612
  placeholder: "Paste callback URL or code here",
597
613
  value: "",
@@ -612,9 +628,9 @@ export function openCommandDialog(api, payload, apply) {
612
628
  api.ui.dialog.replace(() => _$createComponent(DialogPrompt, {
613
629
  title: "OAuth sign-in \\u2014 label",
614
630
  description: () => (() => {
615
- var _el$14 = _$createElement("text");
616
- _$insertNode(_el$14, _$createTextNode(`A short name for this account (optional).`));
617
- return _el$14;
631
+ var _el$17 = _$createElement("text");
632
+ _$insertNode(_el$17, _$createTextNode(`A short name for this account (optional).`));
633
+ return _el$17;
618
634
  })(),
619
635
  placeholder: "e.g. work",
620
636
  value: "",
@@ -324,8 +324,8 @@ function QuotaRow(props) {
324
324
  // Pacing is computed here — per window, against the wall clock at render time
325
325
  // (re-evaluated on every state poll) — and disabled by passing false.
326
326
  function AccountBlock(props) {
327
- const statusWord = () => props.needsReauth ? 're-login' : props.active ? 'active' : 'idle';
328
- const statusTone = () => props.needsReauth ? 'err' : props.active ? 'ok' : 'muted';
327
+ const statusWord = () => props.needsReauth ? 're-login' : props.vaultReauth ? 'vault reauth' : props.active ? 'active' : 'idle';
328
+ const statusTone = () => props.needsReauth || props.vaultReauth ? 'warn' : props.active ? 'ok' : 'muted';
329
329
  const pacingFor = (window, windowMs) => props.pacingEnabled && window ? computeQuotaPacing(window, windowMs, Date.now()) : null;
330
330
  return (() => {
331
331
  var _el$22 = _$createElement("box"),
@@ -680,7 +680,8 @@ function QuotaSidebar(props) {
680
680
  const quotaBackedOff = () => state().main?.quotaBackedOff === true;
681
681
  const refreshBackedOff = () => state().main?.refreshBackedOff === true;
682
682
  const needsReauth = () => enabledFallbacks().some(f => f.needsReauth);
683
- const degraded = () => quotaBackedOff() || refreshBackedOff() || needsReauth();
683
+ const vaultReauth = () => enabledFallbacks().some(f => f.vaultReauth);
684
+ const degraded = () => quotaBackedOff() || refreshBackedOff() || needsReauth() || vaultReauth();
684
685
  const fableRecoverySummary = () => getFableRecoverySummary(state(), props.sessionId);
685
686
  const fableRecoveryTone = () => state().fableRecoveries?.find(recovery => recovery.sessionId === props.sessionId)?.mode === 'fable' ? 'ok' : 'warn';
686
687
  const cacheKeep = () => state().cacheKeep;
@@ -921,6 +922,9 @@ function QuotaSidebar(props) {
921
922
  get needsReauth() {
922
923
  return fb.needsReauth;
923
924
  },
925
+ get vaultReauth() {
926
+ return fb.vaultReauth;
927
+ },
924
928
  marginTop: 1
925
929
  })
926
930
  });