@cortexkit/opencode-anthropic-auth 1.14.0 → 1.15.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.
@@ -27,6 +27,13 @@ export interface SidebarAccountState {
27
27
  needsReauth: boolean
28
28
  }
29
29
 
30
+ export interface FableRecoverySidebarState {
31
+ sessionId: string
32
+ mode: 'opus' | 'fable'
33
+ remaining: number
34
+ changedAt: number
35
+ }
36
+
30
37
  export interface SidebarState {
31
38
  main: {
32
39
  quota: AccountQuota | null
@@ -45,6 +52,7 @@ export interface SidebarState {
45
52
  window?: string
46
53
  trackedSessions?: number
47
54
  }
55
+ fableRecoveries?: FableRecoverySidebarState[]
48
56
  lastUpdated: number
49
57
  }
50
58
 
@@ -185,6 +193,32 @@ export function normalizeSidebarState(raw: unknown): SidebarState {
185
193
  }
186
194
  }
187
195
 
196
+ const fableRecoveries: FableRecoverySidebarState[] = Array.isArray(
197
+ raw.fableRecoveries,
198
+ )
199
+ ? raw.fableRecoveries
200
+ .filter(isRecord)
201
+ .flatMap((recovery): FableRecoverySidebarState[] => {
202
+ if (
203
+ typeof recovery.sessionId !== 'string' ||
204
+ (recovery.mode !== 'opus' && recovery.mode !== 'fable') ||
205
+ typeof recovery.remaining !== 'number' ||
206
+ !Number.isFinite(recovery.remaining) ||
207
+ typeof recovery.changedAt !== 'number' ||
208
+ !Number.isFinite(recovery.changedAt)
209
+ )
210
+ return []
211
+ return [
212
+ {
213
+ sessionId: recovery.sessionId,
214
+ mode: recovery.mode,
215
+ remaining: Math.max(0, Math.floor(recovery.remaining)),
216
+ changedAt: recovery.changedAt,
217
+ },
218
+ ]
219
+ })
220
+ : []
221
+
188
222
  return {
189
223
  main,
190
224
  fallbacks,
@@ -197,6 +231,7 @@ export function normalizeSidebarState(raw: unknown): SidebarState {
197
231
  ? raw.fastMode
198
232
  : DEFAULT_SIDEBAR_STATE.fastMode,
199
233
  cacheKeep,
234
+ fableRecoveries: fableRecoveries.length > 0 ? fableRecoveries : undefined,
200
235
  lastUpdated: typeof raw.lastUpdated === 'number' ? raw.lastUpdated : 0,
201
236
  }
202
237
  }
@@ -265,6 +300,18 @@ export function formatScopedQuotaLabel(title: string) {
265
300
  return /^fable$/i.test(label) ? 'Fa' : label
266
301
  }
267
302
 
303
+ export function getFableRecoverySummary(
304
+ state: SidebarState,
305
+ sessionId: string,
306
+ ): string | undefined {
307
+ const recovery = state.fableRecoveries?.find(
308
+ (candidate) => candidate.sessionId === sessionId,
309
+ )
310
+ if (!recovery) return undefined
311
+ if (recovery.mode === 'fable') return 'Fable 5 · restored'
312
+ return `Opus 4.8 · ${recovery.remaining} left`
313
+ }
314
+
268
315
  export function getCollapsedQuotaSummary(quota: AccountQuota | null): {
269
316
  fiveHourUsedPercent: number | null
270
317
  sevenDayUsedPercent: number | null
package/src/tui.tsx CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  FIVE_HOUR_MS,
26
26
  formatScopedQuotaLabel,
27
27
  getCollapsedQuotaSummary,
28
+ getFableRecoverySummary,
28
29
  getSidebarState,
29
30
  type QuotaPacing,
30
31
  resolveActiveAccount,
@@ -501,6 +502,7 @@ function createSidebarController(
501
502
  function QuotaSidebar(props: {
502
503
  api: TuiPluginApi
503
504
  controller: SidebarController
505
+ sessionId: string
504
506
  }) {
505
507
  const prefs = props.controller.prefs
506
508
  const collapsed = props.controller.collapsed
@@ -604,6 +606,14 @@ function QuotaSidebar(props: {
604
606
  const needsReauth = () => enabledFallbacks().some((f) => f.needsReauth)
605
607
  const degraded = () => quotaBackedOff() || refreshBackedOff() || needsReauth()
606
608
 
609
+ const fableRecoverySummary = () =>
610
+ getFableRecoverySummary(state(), props.sessionId)
611
+ const fableRecoveryTone = (): Tone =>
612
+ state().fableRecoveries?.find(
613
+ (recovery) => recovery.sessionId === props.sessionId,
614
+ )?.mode === 'opus'
615
+ ? 'warn'
616
+ : 'ok'
607
617
  const cacheKeep = () => state().cacheKeep
608
618
  const showCache = () =>
609
619
  prefs().sections.cache && cacheKeep() != null && cacheKeep()?.window != null
@@ -679,6 +689,15 @@ function QuotaSidebar(props: {
679
689
  </text>
680
690
  </CollapsedRow>
681
691
  </Show>
692
+ <Show when={fableRecoverySummary()}>
693
+ {(summary: () => string) => (
694
+ <CollapsedRow theme={theme()} label='Recovery'>
695
+ <text fg={toneColor(theme(), fableRecoveryTone())}>
696
+ <b>{summary()}</b>
697
+ </text>
698
+ </CollapsedRow>
699
+ )}
700
+ </Show>
682
701
  </Show>
683
702
 
684
703
  {/* Expanded: full sections. Also render when there's no data so the
@@ -745,6 +764,17 @@ function QuotaSidebar(props: {
745
764
  />
746
765
  </Show>
747
766
 
767
+ <Show when={fableRecoverySummary()}>
768
+ {(summary: () => string) => (
769
+ <StatRow
770
+ theme={theme()}
771
+ label='Recovery'
772
+ value={summary()}
773
+ tone={fableRecoveryTone()}
774
+ />
775
+ )}
776
+ </Show>
777
+
748
778
  {/* Cache */}
749
779
  <Show when={showCache()}>
750
780
  <SectionHeader theme={theme()} title='Cache' />
@@ -795,8 +825,14 @@ const tui: TuiPlugin = async (api) => {
795
825
  api.slots.register({
796
826
  order: computeEffectiveOrder(root, PLUGIN_KEY, DEFAULT_SLOT_ORDER),
797
827
  slots: {
798
- sidebar_content(_ctx: unknown, _props: { session_id: string }) {
799
- return <QuotaSidebar api={api} controller={controller} />
828
+ sidebar_content(_ctx: unknown, props: { session_id: string }) {
829
+ return (
830
+ <QuotaSidebar
831
+ api={api}
832
+ controller={controller}
833
+ sessionId={props.session_id}
834
+ />
835
+ )
800
836
  },
801
837
  },
802
838
  })
@@ -1,2 +0,0 @@
1
- import{mkdir as q,readFile as M,writeFile as b}from"node:fs/promises";import{tmpdir as L}from"node:os";import{dirname as k,join as g}from"node:path";var R="OPENCODE_ANTHROPIC_AUTH_SIDEBAR_STATE_FILE",f=g(L(),"opencode-anthropic-auth"),I=g(f,"sidebar-state.json");function h(){return process.env[R]||I}var K={main:{quota:null},fallbacks:[],activeId:void 0,route:"main",relay:null,fastMode:!1,lastUpdated:0};function G(J){return J!==null&&typeof J==="object"&&!Array.isArray(J)}function z(J){if(!G(J))return;let X=Number(J.usedPercent),Y=Number(J.remainingPercent);if(!Number.isFinite(X)||!Number.isFinite(Y))return;return{usedPercent:X,remainingPercent:Y,resetsAt:typeof J.resetsAt==="string"?J.resetsAt:void 0}}function N(J){if(!G(J))return null;let X={},Y=z(J.five_hour),Z=z(J.seven_day);if(Y)X.five_hour=Y;if(Z)X.seven_day=Z;if(Array.isArray(J.scoped)){let $=J.scoped.map((x)=>{if(!G(x))return;let j=z(x);if(!j)return;if(typeof x.id!=="string"||!x.id.trim())return;if(typeof x.title!=="string"||!x.title.trim())return;if(typeof x.modelName!=="string"||!x.modelName.trim())return;let V=typeof x.modelId==="string"&&x.modelId.trim()?x.modelId.trim():void 0;return{...j,id:x.id.trim(),title:x.title.trim(),...V&&{modelId:V},modelName:x.modelName.trim()}}).filter((x)=>x!=null);X.scoped=$}return Object.keys(X).length?X:null}function F(J){if(!G(J))return{...K};let X={quota:null};if(G(J.main)){let x=J.main;if(X.quota=N(x.quota),typeof x.quotaBackedOff==="boolean")X.quotaBackedOff=x.quotaBackedOff;if(typeof x.quotaBackoffUntil==="number")X.quotaBackoffUntil=x.quotaBackoffUntil;if(typeof x.refreshBackedOff==="boolean")X.refreshBackedOff=x.refreshBackedOff;if(typeof x.refreshBackoffUntil==="number")X.refreshBackoffUntil=x.refreshBackoffUntil}let Y=Array.isArray(J.fallbacks)?J.fallbacks.filter(G).filter((x)=>typeof x.id==="string").map((x)=>({id:x.id,label:typeof x.label==="string"?x.label:void 0,quota:N(x.quota),enabled:typeof x.enabled==="boolean"?x.enabled:!1,needsReauth:typeof x.needsReauth==="boolean"?x.needsReauth:!1})):[],Z=null;if(G(J.relay)){let x=J.relay;if(typeof x.enabled==="boolean"&&typeof x.transport==="string")Z={enabled:x.enabled,transport:x.transport}}let $;if(G(J.cacheKeep)){let x=J.cacheKeep;if(typeof x.enabled==="boolean")$={enabled:x.enabled,window:typeof x.window==="string"?x.window:void 0,trackedSessions:typeof x.trackedSessions==="number"?x.trackedSessions:void 0}}return{main:X,fallbacks:Y,activeId:typeof J.activeId==="string"?J.activeId:void 0,route:typeof J.route==="string"?J.route:K.route,relay:Z,fastMode:typeof J.fastMode==="boolean"?J.fastMode:K.fastMode,cacheKeep:$,lastUpdated:typeof J.lastUpdated==="number"?J.lastUpdated:0}}var W=Promise.resolve();async function P(){try{let J=await M(h(),"utf8");return F(JSON.parse(J))}catch{return K}}async function A(J,X=h()){return W=W.then(async()=>{await q(k(X),{recursive:!0}),await b(X,JSON.stringify(J),"utf8")}).catch(()=>{}),W}async function m(){return W}function v(J){let X=J.activeId;if(X&&X!=="main"){let Y=J.fallbacks?.find((Z)=>Z.enabled&&Z.id===X);if(Y)return{id:Y.id,name:Y.label??Y.id,quota:Y.quota}}return{id:"main",name:"main",quota:J.main?.quota??null}}function U(J){let X=J.replace(/\s+only$/i,"").trim();return/^fable$/i.test(X)?"Fa":X}function y(J){let X=J?.five_hour?.usedPercent??null,Y=J?.seven_day?.usedPercent??null,Z=J?.scoped??[],$=Z.map((V)=>V.usedPercent);if(X==null&&Y==null&&Z.length===0)return{fiveHourUsedPercent:X,sevenDayUsedPercent:Y,scopedUsedPercents:$,text:null};let x=Z.map((V)=>`${U(V.title)}: ${Math.round(V.usedPercent)}%`),j=X==null&&Y==null?[]:[`5h: ${X==null?"—":`${Math.round(X)}%`}`,`7d: ${Y==null?"—":`${Math.round(Y)}%`}`];return{fiveHourUsedPercent:X,sevenDayUsedPercent:Y,scopedUsedPercents:$,text:[...j,...x].join(" ")}}var u=18000000,l=604800000,D=300000,_=0.01,p=1;function c(J,X,Y){if(!J.resetsAt)return null;let Z=new Date(J.resetsAt).getTime();if(!Number.isFinite(Z))return null;let $=Z-X,x=Y-$;if(x<D)return null;if(x<X*_)return null;if(x>=X)return null;let j=J.usedPercent,V=Math.min(Math.max(x/X*100,0),100),B=j-V,C=Math.abs(B)<p?"on-pace":B>0?"deficit":"reserve",O=null;if(j>0){let H=x*100/j,Q=$+H;if(Q<Z)O=new Date(Q).toISOString()}return{pacePercent:V,deltaPercent:B,state:C,runsOutAt:O}}
2
- export{h as Db,K as Eb,F as Fb,P as Gb,A as Hb,m as Ib,v as Jb,U as Kb,y as Lb,u as Mb,l as Nb,c as Ob};