@cortexkit/opencode-anthropic-auth 2.2.8 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/cli.js +45 -42
  2. package/dist/index-32m0nard.js +43 -0
  3. package/dist/index-46e2gk3c.js +2 -0
  4. package/dist/index-dpnhamzw.js +2 -0
  5. package/dist/index-gvswxab8.js +2 -0
  6. package/dist/index-hc7bm3yf.js +1 -0
  7. package/dist/index.js +1 -1
  8. package/dist/plugin-test-handles.d.ts +26 -0
  9. package/dist/rpc/port-file.d.ts +6 -0
  10. package/dist/rpc/port-file.js +1 -1
  11. package/dist/rpc/rpc-client.js +1 -1
  12. package/dist/rpc/rpc-dir.js +1 -1
  13. package/dist/sidebar-state.d.ts +6 -3
  14. package/dist/sidebar-state.js +1 -1
  15. package/dist/tui/claude-sidebar.d.ts +58 -0
  16. package/dist/tui/menu-status.d.ts +70 -0
  17. package/dist/tui-preferences.js +2 -2
  18. package/dist/v2/adapter.d.ts +29 -5
  19. package/dist/v2/cachekeep.d.ts +10 -1
  20. package/dist/v2/server.js +10 -10
  21. package/dist/v2/tui.d.ts +12 -0
  22. package/dist/v2/tui.js +4 -5
  23. package/package.json +2 -2
  24. package/src/rpc/port-file.ts +11 -1
  25. package/src/rpc/rpc-dir.ts +7 -2
  26. package/src/sidebar-state.ts +55 -46
  27. package/src/tui/claude-sidebar.tsx +155 -15
  28. package/src/tui/entry.mjs +13 -0
  29. package/src/tui/menu-status.tsx +300 -0
  30. package/src/tui-compiled/rpc/port-file.ts +11 -1
  31. package/src/tui-compiled/rpc/rpc-dir.ts +7 -2
  32. package/src/tui-compiled/sidebar-state.ts +55 -46
  33. package/src/tui-compiled/tui/claude-sidebar.tsx +112 -12
  34. package/src/tui-compiled/tui/menu-status.tsx +388 -0
  35. package/src/tui-compiled/tui-preferences.ts +32 -3
  36. package/src/tui-preferences.ts +32 -3
  37. package/dist/index-0jd4jg49.js +0 -43
  38. package/dist/index-bcp23wwb.js +0 -2
  39. package/dist/index-c8ehrd0p.js +0 -1
  40. package/dist/index-j6x60aqq.js +0 -2
  41. package/dist/index-nm4pjrt8.js +0 -2
@@ -0,0 +1,26 @@
1
+ import type { AccountStorage, acquireNativeAccountRuntime, CacheKeepManager, CustodyStatusState, PrimeManager, ProviderAccountUuid, QuotaManager } from '@cortexkit/anthropic-auth-core';
2
+ export interface PluginTestHandles {
3
+ primeManager: PrimeManager;
4
+ quotaManager: QuotaManager;
5
+ cacheKeepManager: CacheKeepManager;
6
+ resolveMainQuotaIdentity: (accessToken: string, model?: string, credentialAccountUuid?: string, credentialRecordVersion?: number) => Promise<{
7
+ quotaKey: string | undefined;
8
+ providerAccountUuid: ProviderAccountUuid | undefined;
9
+ generation: number;
10
+ routingLineage?: string;
11
+ stale: boolean;
12
+ state: CustodyStatusState;
13
+ }>;
14
+ resolveSidebarQuotaAccess: () => Promise<{
15
+ storage: AccountStorage | null;
16
+ access: undefined;
17
+ }>;
18
+ refreshSidebarQuota: () => Promise<void>;
19
+ fallbackRefreshReady: Promise<void>;
20
+ readonly scopedRuntime: ReturnType<typeof acquireNativeAccountRuntime>['vault'];
21
+ notificationMessageIdBeforeAssistant: (latestAssistantMessageId: string, latestUserMessageId?: string) => string | undefined;
22
+ trackDesktopNoticeMessageId: (sessionId: string, messageId: string) => void;
23
+ isDesktopNoticeMessage: (sessionId: string, messageId?: string) => boolean;
24
+ }
25
+ export declare let pluginTestHandles: WeakMap<object, PluginTestHandles> | undefined;
26
+ export declare function enablePluginTestHandles(): WeakMap<object, PluginTestHandles>;
@@ -1,8 +1,14 @@
1
+ import { type WriterStamp } from '@cortexkit/anthropic-auth-core';
1
2
  export interface PortFileEntry {
2
3
  port: number;
3
4
  token: string;
4
5
  pid: number;
5
6
  startedAt: number;
7
+ /**
8
+ * Present in files written by 2.3.0 and later, so a later version can tell
9
+ * them from files of older versions. Older readers ignore it.
10
+ */
11
+ writer?: WriterStamp;
6
12
  }
7
13
  export declare function writePortFile(dir: string, entry: {
8
14
  port: number;
@@ -1 +1 @@
1
- import{ga as a,ha as b}from"../index-bcp23wwb.js";import"../index-71temqvq.js";export{a as writePortFile,b as discoverPortFile};
1
+ import{ga as a,ha as b}from"../index-gvswxab8.js";import"../index-71temqvq.js";export{a as writePortFile,b as discoverPortFile};
@@ -1 +1 @@
1
- import{ha as s}from"../index-bcp23wwb.js";import"../index-71temqvq.js";async function i(e,o,t,n){let r=await s(e,n);if(!r)return null;let a=new AbortController,l=setTimeout(()=>a.abort(),2000);try{let p=await fetch(`http://127.0.0.1:${r.port}/rpc/${o}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.token}`},body:JSON.stringify(t),signal:a.signal});if(!p.ok)return null;return await p.json()}catch{return null}finally{clearTimeout(l)}}function c(e,o){return{async pending(t,n){return(await i(e,"pending-notifications",{lastReceivedId:t,sessionId:n},o))?.messages??[]},async apply(t){return await i(e,"apply",{...t},o)??{text:"apply failed",knobs:{}}},async applyMenu(t){if(t.command!=="claude"||!t.sessionId?.trim())throw TypeError("A claude menu sessionId is required");let n=await i(e,"apply-menu",{...t},o);if(!n)throw Error("Menu apply unavailable; outcome unknown");return n}}}export{c as createRpcClient};
1
+ import{ha as s}from"../index-gvswxab8.js";import"../index-71temqvq.js";async function i(e,o,t,n){let r=await s(e,n);if(!r)return null;let a=new AbortController,l=setTimeout(()=>a.abort(),2000);try{let p=await fetch(`http://127.0.0.1:${r.port}/rpc/${o}`,{method:"POST",headers:{"content-type":"application/json",authorization:`Bearer ${r.token}`},body:JSON.stringify(t),signal:a.signal});if(!p.ok)return null;return await p.json()}catch{return null}finally{clearTimeout(l)}}function c(e,o){return{async pending(t,n){return(await i(e,"pending-notifications",{lastReceivedId:t,sessionId:n},o))?.messages??[]},async apply(t){return await i(e,"apply",{...t},o)??{text:"apply failed",knobs:{}}},async applyMenu(t){if(t.command!=="claude"||!t.sessionId?.trim())throw TypeError("A claude menu sessionId is required");let n=await i(e,"apply-menu",{...t},o);if(!n)throw Error("Menu apply unavailable; outcome unknown");return n}}}export{c as createRpcClient};
@@ -1 +1 @@
1
- import{s as a,t as b}from"../index-c8ehrd0p.js";import"../index-71temqvq.js";export{a as tmpdir,b as getRpcDir};
1
+ import{s as a,t as b}from"../index-hc7bm3yf.js";import"../index-71temqvq.js";export{a as tmpdir,b as getRpcDir};
@@ -35,7 +35,7 @@ export interface AccountQuota {
35
35
  }
36
36
  export interface SidebarAccountState {
37
37
  id: string;
38
- label: string | undefined;
38
+ label?: string;
39
39
  quota: AccountQuota | null;
40
40
  enabled: boolean;
41
41
  stateLine?: string;
@@ -82,7 +82,7 @@ export interface SidebarState {
82
82
  refreshBackoffUntil?: number;
83
83
  };
84
84
  fallbacks: SidebarAccountState[];
85
- activeId: string | undefined;
85
+ activeId?: string;
86
86
  route: string;
87
87
  relay: {
88
88
  enabled: boolean;
@@ -139,7 +139,10 @@ export interface SidebarStateWriteOptions {
139
139
  }) | undefined | Promise<(Pick<SidebarState, 'activeId' | 'route'> & {
140
140
  state?: SidebarState;
141
141
  }) | undefined>;
142
- onRoutingResolved?: (routing: Pick<SidebarState, 'activeId' | 'route'>) => void;
142
+ onRoutingResolved?: (routing: {
143
+ activeId: string | undefined;
144
+ route: string;
145
+ }) => void;
143
146
  }
144
147
  export declare function setSidebarState(state: SidebarState, stateFile?: string, options?: SidebarStateWriteOptions): Promise<void>;
145
148
  export declare function drainSidebarWrites(): Promise<void>;
@@ -1 +1 @@
1
- import{$ as u,H as a,I as b,J as c,K as d,L as e,M as f,N as g,O as h,P as i,Q as j,R as k,S as l,T as m,U as n,V as o,W as p,X as q,Y as r,Z as s,_ as t,aa as v,ba as w,ca as x,da as y,ea as z,fa as A}from"./index-j6x60aqq.js";import"./index-71temqvq.js";export{i as setSidebarState,r as scopedQuotaShortNames,k as resolveActiveAccount,s as quotaLabelColumnWidth,c as normalizeSidebarState,a as getSidebarStateFile,h as getSidebarState,f as getInitialSidebarRoutingTestHooks,p as getFableRecoverySummary,w as getCollapsedQuotaSummary,x as getCollapsedAccounts,q as formatQuotaRowLabel,m as formatPrimeTime,n as formatPrimeCost,o as formatPrimeAccountValue,l as formatFallbackModelLabel,u as fitQuotaRow,v as fitPaceLine,j as drainSidebarWrites,A as computeQuotaPacing,d as __setSidebarStateWriteTestHooks,e as __setInitialSidebarRoutingTestHooks,g as __acquireSidebarStateLockForTest,z as SEVEN_DAY_MS,t as QUOTA_BAR_MIN_CELLS,y as FIVE_HOUR_MS,b as DEFAULT_SIDEBAR_STATE};
1
+ import{$ as u,H as a,I as b,J as c,K as d,L as e,M as f,N as g,O as h,P as i,Q as j,R as k,S as l,T as m,U as n,V as o,W as p,X as q,Y as r,Z as s,_ as t,aa as v,ba as w,ca as x,da as y,ea as z,fa as A}from"./index-46e2gk3c.js";import"./index-71temqvq.js";export{i as setSidebarState,r as scopedQuotaShortNames,k as resolveActiveAccount,s as quotaLabelColumnWidth,c as normalizeSidebarState,a as getSidebarStateFile,h as getSidebarState,f as getInitialSidebarRoutingTestHooks,p as getFableRecoverySummary,w as getCollapsedQuotaSummary,x as getCollapsedAccounts,q as formatQuotaRowLabel,m as formatPrimeTime,n as formatPrimeCost,o as formatPrimeAccountValue,l as formatFallbackModelLabel,u as fitQuotaRow,v as fitPaceLine,j as drainSidebarWrites,A as computeQuotaPacing,d as __setSidebarStateWriteTestHooks,e as __setInitialSidebarRoutingTestHooks,g as __acquireSidebarStateLockForTest,z as SEVEN_DAY_MS,t as QUOTA_BAR_MIN_CELLS,y as FIVE_HOUR_MS,b as DEFAULT_SIDEBAR_STATE};
@@ -41,6 +41,12 @@ export interface SidebarController {
41
41
  toggleCollapsed: () => void;
42
42
  /** Stops the preference watcher; OpenCode 1 keeps it for the process. */
43
43
  dispose: () => void;
44
+ /**
45
+ * However many refreshes in a row have failed, a retry never waits longer
46
+ * than this. Every attempt costs the server a full runtime read, so a
47
+ * failing sidebar must not keep trying at the poll rate forever.
48
+ */
49
+ retryMaxMs: number;
44
50
  }
45
51
  export declare function createSidebarController(initialPrefs: AnthropicAuthTuiPrefs): SidebarController;
46
52
  /** The sidebar panel for one session; the host owns polling and the theme. */
@@ -95,5 +101,57 @@ export interface ClaudeSidebarHost {
95
101
  }
96
102
  /** Reads one session's sidebar state from the location's server. */
97
103
  export type ReadSidebarState = (sessionID: string, signal: AbortSignal) => Promise<SidebarState>;
104
+ /**
105
+ * What the sidebar reads and draws with, independent of the host chrome.
106
+ * The timer functions default to the global ones; a test passes its own so it
107
+ * can drive the refresh schedule without touching the shared globals.
108
+ */
109
+ export interface HostSidebarPropsState {
110
+ read: ReadSidebarState;
111
+ controller: SidebarController;
112
+ sessionId: string;
113
+ setTimeoutImpl?: typeof globalThis.setTimeout;
114
+ /** Clears a handle `setTimeoutImpl` returned, whatever type that was. */
115
+ clearTimeoutImpl?: (handle: unknown) => void;
116
+ }
117
+ /** The refresh loop's own timers, so a test can drive its schedule. */
118
+ export interface SidebarScheduleTimers {
119
+ setTimeoutImpl?: typeof globalThis.setTimeout;
120
+ clearTimeoutImpl?: (handle: unknown) => void;
121
+ }
122
+ /**
123
+ * Delay before the next refresh after `failures` failed reads in a row, each
124
+ * one longer than the last until the controller's limit. A successful read
125
+ * resets the count, so a healthy server is polled at the configured rate. A
126
+ * failed read still costs the server a full runtime read, so retrying at the
127
+ * poll rate keeps that cost alive for as long as the failure lasts.
128
+ */
129
+ export declare function sidebarRetryDelay(pollMs: number, failures: number, retryMaxMs: number): number;
130
+ /** Starts and stops the refresh schedule the sidebar lives on. */
131
+ export interface SidebarSchedule {
132
+ /**
133
+ * Reads once and then keeps the retry timer running. Safe to call more than
134
+ * once: a running schedule is left alone.
135
+ */
136
+ start: () => void;
137
+ /**
138
+ * Stops the schedule for good: clears the waiting timer and aborts a read
139
+ * still in flight, so it cannot queue another one. The item that unmounts a
140
+ * sidebar calls this; without it, a failing refresh would keep polling the
141
+ * server from a sidebar nobody is looking at.
142
+ */
143
+ stop: () => void;
144
+ }
145
+ export declare function createSidebarSchedule(options: {
146
+ read: ReadSidebarState;
147
+ sessionId: string;
148
+ pollRate: () => {
149
+ pollMs: number;
150
+ retryMaxMs: number;
151
+ };
152
+ /** Receives each answer that differs from the one before it. */
153
+ onState: (state: SidebarState) => void;
154
+ } & SidebarScheduleTimers): SidebarSchedule;
155
+ export declare function useHostSidebarState(props: HostSidebarPropsState): () => SidebarState;
98
156
  /** Claims the OpenCode 2 session sidebar; the returned function releases it. */
99
157
  export declare function mountClaudeSidebar(host: ClaudeSidebarHost, read: ReadSidebarState): Promise<() => void>;
@@ -0,0 +1,70 @@
1
+ /** @jsxImportSource @opentui/solid */
2
+ import { type JSX } from 'solid-js';
3
+ import type { SidebarState } from '../sidebar-state.js';
4
+ import { type AnthropicAuthTuiPrefs } from '../tui-preferences.js';
5
+ import { type HostTheme, type SidebarTheme } from './claude-sidebar.js';
6
+ /** One status line, classified for drawing. */
7
+ export type StatusLine = {
8
+ readonly kind: 'heading';
9
+ readonly level: number;
10
+ readonly text: string;
11
+ } | {
12
+ readonly kind: 'bullet';
13
+ readonly indent: number;
14
+ readonly text: string;
15
+ } | {
16
+ readonly kind: 'text';
17
+ readonly text: string;
18
+ } | {
19
+ readonly kind: 'blank';
20
+ };
21
+ /**
22
+ * Splits a section's status lines (each may hold several lines) and classifies
23
+ * each one. Only line-leading Markdown is read: `#` headings and `-`, `*` or
24
+ * `+` bullets. Everything else, including any `*` inside a line, stays as
25
+ * written. Runs of blank lines collapse to one, and leading or trailing blank
26
+ * lines are dropped.
27
+ */
28
+ export declare function parseStatusLines(lines: readonly string[]): StatusLine[];
29
+ /** Draws status lines with headings and bullets styled, not as Markdown. */
30
+ export declare function StatusText(props: {
31
+ readonly lines: readonly string[];
32
+ readonly theme: SidebarTheme;
33
+ }): JSX.Element;
34
+ /**
35
+ * OpenCode 1's quota view: one account block for main and for each enabled or
36
+ * vault-held fallback, as the sidebar draws them.
37
+ */
38
+ export declare function QuotaStatus(props: {
39
+ readonly state: SidebarState;
40
+ readonly theme: SidebarTheme;
41
+ readonly prefs: AnthropicAuthTuiPrefs;
42
+ readonly now: number;
43
+ }): JSX.Element;
44
+ /** One section's status, as the `/claude` menu hands it over. */
45
+ export interface MenuStatusView {
46
+ readonly title: string;
47
+ readonly lines: readonly string[];
48
+ /**
49
+ * Reads the sidebar's quota state; given for the Quota section only, whose
50
+ * view then draws account blocks instead of the text.
51
+ */
52
+ readonly readQuota?: (signal: AbortSignal) => Promise<SidebarState>;
53
+ }
54
+ /** The OpenCode 2 TUI context members the status dialog uses. */
55
+ export interface MenuStatusHost {
56
+ readonly theme: HostTheme;
57
+ readonly ui: {
58
+ readonly dialog: {
59
+ show(render: () => JSX.Element, onClose?: () => void): void;
60
+ set(options: {
61
+ readonly size?: 'medium' | 'large' | 'xlarge';
62
+ }): void;
63
+ };
64
+ };
65
+ }
66
+ /**
67
+ * Shows a section's status in a wide OpenCode 2 dialog. The returned promise
68
+ * settles when the person closes the dialog, or when `signal` aborts.
69
+ */
70
+ export declare function showMenuStatusDialog(host: MenuStatusHost, view: MenuStatusView, signal?: AbortSignal): Promise<void>;
@@ -1,6 +1,6 @@
1
- import"./index-71temqvq.js";import{readFileSync as k,watch as C}from"node:fs";import{mkdir as _,readFile as I,rename as E,writeFile as b}from"node:fs/promises";import{homedir as g}from"node:os";import{basename as F,dirname as P,join as N}from"node:path";import{clearTimeout as D,setTimeout as L}from"node:timers";import{applyEdits as T,modify as y,parse as f}from"jsonc-parser";var v="OPENCODE_TUI_PREFERENCES_FILE",h="tui-preferences.jsonc";function A(){let J=process.env[v];if(J)return J;let z=process.env.OPENCODE_CONFIG_DIR||N(process.env.XDG_CONFIG_HOME||N(g(),".config"),"opencode");return N(z,h)}function H(J){return typeof J==="object"&&J!==null&&!Array.isArray(J)}async function qq(){try{let J=await I(A(),"utf8"),z=[],q=f(J,z,{allowTrailingComma:!0});if(z.length>0)return{};return H(q)?q:{}}catch{return{}}}var m="anthropic-auth",p=160,R={forceToTop:!1,order:p,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 $(J,z){return typeof J==="boolean"?J:z}function Y(J,z,q,X){if(typeof J!=="number"||!Number.isFinite(J))return z;return Math.min(Math.max(Math.round(J),q),X)}function c(J,z,q){if(typeof J!=="string"||J.length===0)return z;return J.slice(0,q)}function w(J,z){if(typeof J!=="string")return z;return[...J][0]??z}function zq(J){let z=J[m];if(!H(z))return structuredClone(R);let q=R,X=H(z.header)?z.header:{},Q=H(z.sections)?z.sections:{},Z=H(z.appearance)?z.appearance:{},G=Y(Z.warnThreshold,q.appearance.warnThreshold,0,99),V=Math.max(Y(Z.errorThreshold,q.appearance.errorThreshold,0,100),Math.min(G+1,100));return{forceToTop:$(z.forceToTop,q.forceToTop),order:Y(z.order,q.order,-1e4,1e4),startCollapsed:$(z.startCollapsed,q.startCollapsed),rememberCollapsed:$(z.rememberCollapsed,q.rememberCollapsed),collapsed:typeof z.collapsed==="boolean"?z.collapsed:null,pollMs:Y(z.pollMs,q.pollMs,500,30000),refreshDebounceMs:Y(z.refreshDebounceMs,q.refreshDebounceMs,50,5000),header:{label:c(X.label,q.header.label,20),showVersion:$(X.showVersion,q.header.showVersion)},sections:{quota:$(Q.quota,q.sections.quota),fallbackAccounts:$(Q.fallbackAccounts,q.sections.fallbackAccounts),routing:$(Q.routing,q.sections.routing),cache:$(Q.cache,q.sections.cache),health:$(Q.health,q.sections.health),pacing:$(Q.pacing,q.sections.pacing)},appearance:{barWidth:Y(Z.barWidth,q.appearance.barWidth,4,40),barFilledChar:w(Z.barFilledChar,q.appearance.barFilledChar),barEmptyChar:w(Z.barEmptyChar,q.appearance.barEmptyChar),warnThreshold:G,errorThreshold:V}}}var u=-1e5;function Jq(J,z,q){let X=J[z];if(!H(X))return q;if(X.forceToTop===!0)return u+Object.keys(J).indexOf(z);return Y(X.order,q,-1e4,1e4)}var s=`// Shared preferences for opencode TUI plugins.
1
+ import"./index-71temqvq.js";import{readFileSync as S,statSync as b,watch as F}from"node:fs";import{mkdir as g,readFile as I,rename as T,writeFile as y}from"node:fs/promises";import{homedir as h}from"node:os";import{basename as v,dirname as _,join as N}from"node:path";import{clearTimeout as D,setTimeout as P}from"node:timers";import{applyEdits as f,modify as m,parse as p}from"jsonc-parser";var c="OPENCODE_TUI_PREFERENCES_FILE",u="tui-preferences.jsonc";function K(){let Q=process.env[c];if(Q)return Q;let q=process.env.OPENCODE_CONFIG_DIR||N(process.env.XDG_CONFIG_HOME||N(h(),".config"),"opencode");return N(q,u)}function H(Q){return typeof Q==="object"&&Q!==null&&!Array.isArray(Q)}async function Zq(){try{let Q=await I(K(),"utf8"),q=[],J=p(Q,q,{allowTrailingComma:!0});if(q.length>0)return{};return H(J)?J:{}}catch{return{}}}var s="anthropic-auth",d=160,k={forceToTop:!1,order:d,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 z(Q,q){return typeof Q==="boolean"?Q:q}function B(Q,q,J,Z){if(typeof Q!=="number"||!Number.isFinite(Q))return q;return Math.min(Math.max(Math.round(Q),J),Z)}function o(Q,q,J){if(typeof Q!=="string"||Q.length===0)return q;return Q.slice(0,J)}function x(Q,q){if(typeof Q!=="string")return q;return[...Q][0]??q}function $q(Q){let q=Q[s];if(!H(q))return structuredClone(k);let J=k,Z=H(q.header)?q.header:{},X=H(q.sections)?q.sections:{},$=H(q.appearance)?q.appearance:{},Y=B($.warnThreshold,J.appearance.warnThreshold,0,99),G=Math.max(B($.errorThreshold,J.appearance.errorThreshold,0,100),Math.min(Y+1,100));return{forceToTop:z(q.forceToTop,J.forceToTop),order:B(q.order,J.order,-1e4,1e4),startCollapsed:z(q.startCollapsed,J.startCollapsed),rememberCollapsed:z(q.rememberCollapsed,J.rememberCollapsed),collapsed:typeof q.collapsed==="boolean"?q.collapsed:null,pollMs:B(q.pollMs,J.pollMs,500,30000),refreshDebounceMs:B(q.refreshDebounceMs,J.refreshDebounceMs,50,5000),header:{label:o(Z.label,J.header.label,20),showVersion:z(Z.showVersion,J.header.showVersion)},sections:{quota:z(X.quota,J.sections.quota),fallbackAccounts:z(X.fallbackAccounts,J.sections.fallbackAccounts),routing:z(X.routing,J.sections.routing),cache:z(X.cache,J.sections.cache),health:z(X.health,J.sections.health),pacing:z(X.pacing,J.sections.pacing)},appearance:{barWidth:B($.barWidth,J.appearance.barWidth,4,40),barFilledChar:x($.barFilledChar,J.appearance.barFilledChar),barEmptyChar:x($.barEmptyChar,J.appearance.barEmptyChar),warnThreshold:Y,errorThreshold:G}}}var n=-1e5;function zq(Q,q,J){let Z=Q[q];if(!H(Z))return J;if(Z.forceToTop===!0)return n+Object.keys(Q).indexOf(q);return B(Z.order,J,-1e4,1e4)}var i=`// 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.
5
5
  {}
6
- `;async function d(J,z,q){let X=A();await _(P(X),{recursive:!0});let Q;try{Q=await I(X,"utf8")}catch{Q=""}if(Q.trim()==="")Q=s;let Z=y(Q,[J,...z],q,{formattingOptions:{insertSpaces:!0,tabSize:2}}),G=T(Q,Z),V=`${X}.${process.pid}.tmp`;await b(V,G,"utf8"),await E(V,X)}var U=Promise.resolve();function Qq(J,z,q){return U=U.then(()=>d(J,z,q)).catch(()=>{}),U}var o=150,n=100;function Xq(J,z={}){let q=A(),X=F(q),Q=null,Z=null;try{Z=k(q,"utf8")}catch{}let G=!1,V=async()=>{let W=await I(q,"utf8").catch(()=>null);if(G||W===null)return;if(W===Z)return;Z=W,J()},x=()=>{if(Q)D(Q);Q=L(()=>{Q=null,V()},o)},K=null;try{K=(z.watchDirectory??C)(P(q),(W,j)=>{let S=j===X||j?.startsWith(`${X}.`)&&j.endsWith(".tmp");if(j!=null&&!S)return;x()})}catch{if(Z===null)return()=>{}}let B=null,M=!1,O=()=>{if(G||B)return;B=L(()=>{if(B=null,G||M)return;M=!0,V().finally(()=>{M=!1,O()})},n),B.unref?.()};return O(),()=>{if(G=!0,Q)D(Q);if(B)D(B);K?.close()}}export{Xq as watchTuiPreferences,zq as resolveAnthropicAuthPrefs,qq as readTuiPreferencesFile,Qq as queueTuiPreferenceUpdate,A as getTuiPreferencesFile,Jq as computeEffectiveOrder,v as TUI_PREFS_FILE_ENV,m as PLUGIN_KEY,p as DEFAULT_SLOT_ORDER,R as DEFAULT_PREFS};
6
+ `;async function r(Q,q,J){let Z=K();await g(_(Z),{recursive:!0});let X;try{X=await I(Z,"utf8")}catch{X=""}if(X.trim()==="")X=i;let $=m(X,[Q,...q],J,{formattingOptions:{insertSpaces:!0,tabSize:2}}),Y=f(X,$),G=`${Z}.${process.pid}.tmp`;await y(G,Y,"utf8"),await T(G,Z)}var U=Promise.resolve();function Gq(Q,q,J){return U=U.then(()=>r(Q,q,J)).catch(()=>{}),U}var t=150,l=100;function C(Q){try{let q=b(Q,{bigint:!0});return`${q.ino}:${q.size}:${q.mtimeNs}:${q.ctimeNs}`}catch{return null}}function Vq(Q,q={}){let J=K(),Z=v(J),X=null,$=null;try{$=S(J,"utf8")}catch{}let Y=C(J),G=!1,A=async(R=!1)=>{let V=await C(J);if(V===null)return;if(V===Y&&$!==null&&!R)return;let M=await I(J,"utf8").catch(()=>null);if(G||M===null)return;if(Y=V,M===$)return;$=M,Q()},E=()=>{if(X)D(X);X=P(()=>{X=null,A(!0)},t)},O=null;try{O=(q.watchDirectory??F)(_(J),(R,V)=>{let w=V===Z||V?.startsWith(`${Z}.`)&&V.endsWith(".tmp");if(V!=null&&!w)return;E()})}catch{if($===null)return()=>{}}let W=null,j=!1,L=()=>{if(G||W)return;W=P(()=>{if(W=null,G||j)return;j=!0,A().finally(()=>{j=!1,L()})},l),W.unref?.()};return L(),()=>{if(G=!0,X)D(X);if(W)D(W);O?.close()}}export{Vq as watchTuiPreferences,$q as resolveAnthropicAuthPrefs,Zq as readTuiPreferencesFile,Gq as queueTuiPreferenceUpdate,K as getTuiPreferencesFile,zq as computeEffectiveOrder,c as TUI_PREFS_FILE_ENV,s as PLUGIN_KEY,d as DEFAULT_SLOT_ORDER,k as DEFAULT_PREFS};
@@ -1,5 +1,5 @@
1
- import { AnthropicOAuthOriginError, type ClaudeCodeIdentity, type RequestGzipLatch, TrailingAssistantHistoryError } from '@cortexkit/anthropic-auth-core';
2
- import type { AccountRequest, AttemptOutcome, ChooseAccountInput, HeaderEdits, HostError, LimitSignal, OpenCode2AuthAdapter, RequestScope, Transport } from '@cortexkit/common-auth/opencode2';
1
+ import { AnthropicOAuthOriginError, type ClaudeCodeIdentity, type HolderRegistrationError, type RelocatedError, type RequestGzipLatch, TrailingAssistantHistoryError } from '@cortexkit/anthropic-auth-core';
2
+ import type { AccountRequest, AttemptOutcome, ChooseAccountInput, ChooseAccountResult, HeaderEdits, HostError, LimitSignal, OpenCode2AuthAdapter, RequestScope, Transport } from '@cortexkit/common-auth/opencode2';
3
3
  import { EffortMarkerCorrelationError } from '../effort-history';
4
4
  import { createStrippedStream, rewriteRequestBody } from '../transform';
5
5
  /** The provider OpenCode 2 serves Claude under. */
@@ -150,8 +150,12 @@ export interface NativeAnthropicAttemptOutcome extends AttemptOutcome {
150
150
  * the adapter passes it is rejected at compile time.
151
151
  */
152
152
  export interface NativeAnthropicSource<Q, P> {
153
- /** Picks the account for one request; `undefined` refuses it. */
154
- readonly chooseAccount: (input: ChooseAccountInput) => Promise<string | undefined> | string | undefined;
153
+ /**
154
+ * Picks the account for one request; `undefined` refuses it. In phase
155
+ * `retry` it may instead return a hold, which keeps the refused account and
156
+ * waits the given delay before the host retries.
157
+ */
158
+ readonly chooseAccount: (input: ChooseAccountInput) => Promise<ChooseAccountResult> | ChooseAccountResult;
155
159
  /** Discards one queued choice that the installer will not authorize. */
156
160
  readonly dropChoice?: (input: AccountRequest) => Promise<void> | void;
157
161
  /**
@@ -194,6 +198,14 @@ export interface NativeAnthropicSource<Q, P> {
194
198
  * 401 can be reported against the exact vault receipt version served.
195
199
  */
196
200
  readonly onAttemptEnd?: (input: NativeAnthropicAttemptContext<P>, outcome: NativeAnthropicAttemptOutcome) => Promise<void> | void;
201
+ /**
202
+ * Whether request dumps are enabled in the current custody mode's settings.
203
+ * The adapter consults this before writing any dump, so a stale global flag
204
+ * from another host mode never decides. Sources backed by the native runtime
205
+ * read `dump.enabled` from the current snapshot; synthetic test sources may
206
+ * omit it, in which case the adapter falls back to the Core global flag.
207
+ */
208
+ readonly isDumpEnabled?: () => Promise<boolean> | boolean;
197
209
  /**
198
210
  * Called by the adapter's `forgetSession`; drops whatever the source keeps
199
211
  * for the session.
@@ -220,7 +232,7 @@ export interface NativeAnthropicAdapterDeps<Q, P> {
220
232
  readonly requestGzipLatch?: RequestGzipLatch;
221
233
  }
222
234
  export interface NativeAnthropicAdapter<Q, P> {
223
- readonly adapter: OpenCode2AuthAdapter<Q, NativeAnthropicAttemptData<P>> & {
235
+ readonly adapter: OpenCode2AuthAdapter<Q, NativeAnthropicAttemptData<P>, ChooseAccountResult> & {
224
236
  readonly dropChoice: (input: AccountRequest) => Promise<void> | void;
225
237
  };
226
238
  /**
@@ -288,5 +300,17 @@ export declare class NativeAnthropicLocalRefusal extends Error {
288
300
  readonly check: string;
289
301
  constructor(cause: TrailingAssistantHistoryError | EffortMarkerCorrelationError | AnthropicOAuthOriginError);
290
302
  }
303
+ /**
304
+ * The request was refused because a newer anthropic-auth version moved the
305
+ * account state files this process uses, or because this process could not
306
+ * record its use of a folder it may only use once recorded. Nothing was
307
+ * sent. The message is Core's fixed text and names no path; the plugin log
308
+ * names the folders.
309
+ */
310
+ export declare class NativeAnthropicStateRefusal extends Error {
311
+ readonly kind = "state-relocated";
312
+ readonly providerID = "anthropic";
313
+ constructor(cause: RelocatedError | HolderRegistrationError);
314
+ }
291
315
  export declare function createNativeAnthropicAdapter<Q, P>(deps: NativeAnthropicAdapterDeps<Q, P>): NativeAnthropicAdapter<Q, P>;
292
316
  export {};
@@ -6,10 +6,19 @@ export interface NativeCacheKeepOptions {
6
6
  readonly clearIntervalImpl?: typeof globalThis.clearInterval;
7
7
  readonly registryDirectory?: string;
8
8
  }
9
- /** Keep admitted hybrid-cache prefixes warm using fresh native authorization for each send. */
9
+ /**
10
+ * Keep admitted hybrid-cache prefixes warm using fresh native authorization for
11
+ * each send. Instances for the same account storage share one set of tracked
12
+ * sessions: a later instance takes over sending for sessions an earlier one
13
+ * tracked, and the timer stops only when the last instance is disposed. The
14
+ * sessions themselves outlive the last instance until their cache expires, so
15
+ * an instance that boots for the same storage in that time adopts them.
16
+ */
10
17
  export declare function createNativeCacheKeep(options: NativeCacheKeepOptions & {
11
18
  runtime: NativeAccountRuntime;
12
19
  source: NativeSource;
20
+ /** Identity of the account storage; instances that share it share sessions. */
21
+ storageId: string;
13
22
  fetch?: typeof fetch;
14
23
  isSubagent?: (sessionID: string) => Promise<boolean>;
15
24
  }): {