@cortexkit/opencode-anthropic-auth 1.10.3 → 1.11.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/cli.d.ts +41 -0
- package/dist/cli.js +6 -6
- package/dist/index-7f07xr7k.js +2 -0
- package/dist/{index-p8j7mmfc.js → index-7hq52c3b.js} +1 -1
- package/dist/index-c1phnbjn.js +417 -0
- package/dist/index-srn1rawx.js +2 -0
- package/dist/index-vhcx8tx6.js +1 -0
- package/dist/index-zfddfgk2.js +4 -0
- package/dist/index.js +11 -10
- package/dist/logger-q4dnhr8x.js +1 -0
- package/dist/rpc/port-file.d.ts +1 -1
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +2 -1
- package/dist/rpc/rpc-client.d.ts +1 -1
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state.d.ts +4 -1
- package/dist/sidebar-state.js +1 -1
- package/dist/tui/command-dialogs.d.ts +1 -0
- package/dist/tui-preferences.js +2 -2
- package/package.json +4 -4
- package/src/rpc/port-file.ts +7 -1
- package/src/rpc/protocol.ts +3 -0
- package/src/rpc/rpc-client.ts +10 -3
- package/src/rpc/rpc-dir.ts +2 -2
- package/src/rpc/rpc-server.ts +5 -3
- package/src/sidebar-state.ts +99 -11
- package/src/tui/command-dialogs.tsx +478 -1
- package/src/tui-preferences.ts +51 -16
- package/src/tui.tsx +25 -14
- package/dist/index-3ynbghx3.js +0 -1
- package/dist/index-9yjbmhf1.js +0 -2
- package/dist/index-jb14nj5c.js +0 -2
- package/dist/index-tes31apx.js +0 -410
package/src/rpc/protocol.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export type CommandModalName =
|
|
2
|
+
| 'claude-account'
|
|
2
3
|
| 'claude-cache'
|
|
3
4
|
| 'claude-cachekeep'
|
|
4
5
|
| 'claude-quota'
|
|
@@ -6,6 +7,7 @@ export type CommandModalName =
|
|
|
6
7
|
| 'claude-fast'
|
|
7
8
|
| 'claude-routing'
|
|
8
9
|
| 'claude-killswitch'
|
|
10
|
+
| 'claude-logging'
|
|
9
11
|
|
|
10
12
|
export interface OpenDialogPayload {
|
|
11
13
|
command: CommandModalName
|
|
@@ -23,6 +25,7 @@ export interface RpcNotification {
|
|
|
23
25
|
export interface ApplyRequest {
|
|
24
26
|
command: CommandModalName
|
|
25
27
|
arguments: string
|
|
28
|
+
sessionId?: string
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
export interface ApplyResult {
|
package/src/rpc/rpc-client.ts
CHANGED
|
@@ -13,8 +13,9 @@ async function call<T>(
|
|
|
13
13
|
dir: string,
|
|
14
14
|
method: string,
|
|
15
15
|
params: Record<string, unknown>,
|
|
16
|
+
expectedPid?: number,
|
|
16
17
|
): Promise<T | null> {
|
|
17
|
-
const entry = await discoverPortFile(dir)
|
|
18
|
+
const entry = await discoverPortFile(dir, expectedPid)
|
|
18
19
|
if (!entry) return null
|
|
19
20
|
const controller = new AbortController()
|
|
20
21
|
const timer = setTimeout(() => controller.abort(), 2_000)
|
|
@@ -37,18 +38,24 @@ async function call<T>(
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
export function createRpcClient(dir: string): RpcClient {
|
|
41
|
+
export function createRpcClient(dir: string, expectedPid?: number): RpcClient {
|
|
41
42
|
return {
|
|
42
43
|
async pending(lastReceivedId, sessionId) {
|
|
43
44
|
const out = await call<{ messages: RpcNotification[] }>(
|
|
44
45
|
dir,
|
|
45
46
|
'pending-notifications',
|
|
46
47
|
{ lastReceivedId, sessionId },
|
|
48
|
+
expectedPid,
|
|
47
49
|
)
|
|
48
50
|
return out?.messages ?? []
|
|
49
51
|
},
|
|
50
52
|
async apply(request) {
|
|
51
|
-
const out = await call<ApplyResult>(
|
|
53
|
+
const out = await call<ApplyResult>(
|
|
54
|
+
dir,
|
|
55
|
+
'apply',
|
|
56
|
+
{ ...request },
|
|
57
|
+
expectedPid,
|
|
58
|
+
)
|
|
52
59
|
return out ?? { text: 'apply failed', knobs: {} }
|
|
53
60
|
},
|
|
54
61
|
}
|
package/src/rpc/rpc-dir.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto'
|
|
2
2
|
import { homedir, tmpdir } from 'node:os'
|
|
3
|
-
import { join } from 'node:path'
|
|
3
|
+
import { join, resolve } from 'node:path'
|
|
4
4
|
|
|
5
5
|
const RPC_DIR_ENV = 'OPENCODE_ANTHROPIC_AUTH_RPC_DIR'
|
|
6
6
|
|
|
7
7
|
// Both processes must resolve the SAME dir from the SAME project directory.
|
|
8
8
|
export function getRpcDir(projectDirectory: string): string {
|
|
9
9
|
const override = process.env[RPC_DIR_ENV]?.trim()
|
|
10
|
-
if (override) return override
|
|
10
|
+
if (override) return resolve(projectDirectory, override)
|
|
11
11
|
const hash = createHash('sha256')
|
|
12
12
|
.update(projectDirectory)
|
|
13
13
|
.digest('hex')
|
package/src/rpc/rpc-server.ts
CHANGED
|
@@ -86,9 +86,11 @@ export async function startRpcServer(
|
|
|
86
86
|
}
|
|
87
87
|
return json(404, { error: 'unknown method' })
|
|
88
88
|
} catch (error) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
if (!res.headersSent && !res.writableEnded && !res.destroyed) {
|
|
90
|
+
json(500, {
|
|
91
|
+
error: error instanceof Error ? error.message : String(error),
|
|
92
|
+
})
|
|
93
|
+
}
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
|
package/src/sidebar-state.ts
CHANGED
|
@@ -14,6 +14,9 @@ export interface SidebarAccountState {
|
|
|
14
14
|
label: string | undefined
|
|
15
15
|
quota: AccountQuota | null
|
|
16
16
|
enabled: boolean
|
|
17
|
+
// True when the account's refresh token is permanently dead (400
|
|
18
|
+
// invalid_grant) and it needs a re-login — distinct from a transient backoff.
|
|
19
|
+
needsReauth: boolean
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
export interface SidebarState {
|
|
@@ -58,24 +61,109 @@ export const DEFAULT_SIDEBAR_STATE: SidebarState = {
|
|
|
58
61
|
fastMode: false,
|
|
59
62
|
lastUpdated: 0,
|
|
60
63
|
}
|
|
64
|
+
function isRecord(v: unknown): v is Record<string, unknown> {
|
|
65
|
+
return v !== null && typeof v === 'object' && !Array.isArray(v)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function normalizeSidebarState(raw: unknown): SidebarState {
|
|
69
|
+
if (!isRecord(raw)) return { ...DEFAULT_SIDEBAR_STATE }
|
|
70
|
+
|
|
71
|
+
const main: SidebarState['main'] = { quota: null }
|
|
72
|
+
if (isRecord(raw.main)) {
|
|
73
|
+
const m = raw.main
|
|
74
|
+
main.quota = isRecord(m.quota) ? (m.quota as AccountQuota) : null
|
|
75
|
+
if (typeof m.quotaBackedOff === 'boolean')
|
|
76
|
+
main.quotaBackedOff = m.quotaBackedOff
|
|
77
|
+
if (typeof m.quotaBackoffUntil === 'number')
|
|
78
|
+
main.quotaBackoffUntil = m.quotaBackoffUntil
|
|
79
|
+
if (typeof m.refreshBackedOff === 'boolean')
|
|
80
|
+
main.refreshBackedOff = m.refreshBackedOff
|
|
81
|
+
if (typeof m.refreshBackoffUntil === 'number')
|
|
82
|
+
main.refreshBackoffUntil = m.refreshBackoffUntil
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const fallbacks: SidebarAccountState[] = Array.isArray(raw.fallbacks)
|
|
86
|
+
? raw.fallbacks
|
|
87
|
+
.filter(isRecord)
|
|
88
|
+
.filter((entry) => typeof entry.id === 'string')
|
|
89
|
+
.map((entry) => ({
|
|
90
|
+
id: entry.id as string,
|
|
91
|
+
label: typeof entry.label === 'string' ? entry.label : undefined,
|
|
92
|
+
quota: isRecord(entry.quota) ? (entry.quota as AccountQuota) : null,
|
|
93
|
+
enabled: typeof entry.enabled === 'boolean' ? entry.enabled : false,
|
|
94
|
+
needsReauth:
|
|
95
|
+
typeof entry.needsReauth === 'boolean' ? entry.needsReauth : false,
|
|
96
|
+
}))
|
|
97
|
+
: []
|
|
98
|
+
|
|
99
|
+
let relay: SidebarState['relay'] = null
|
|
100
|
+
if (isRecord(raw.relay)) {
|
|
101
|
+
const r = raw.relay
|
|
102
|
+
if (typeof r.enabled === 'boolean' && typeof r.transport === 'string') {
|
|
103
|
+
relay = { enabled: r.enabled, transport: r.transport }
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
let cacheKeep: SidebarState['cacheKeep']
|
|
108
|
+
if (isRecord(raw.cacheKeep)) {
|
|
109
|
+
const ck = raw.cacheKeep
|
|
110
|
+
if (typeof ck.enabled === 'boolean') {
|
|
111
|
+
cacheKeep = {
|
|
112
|
+
enabled: ck.enabled,
|
|
113
|
+
window: typeof ck.window === 'string' ? ck.window : undefined,
|
|
114
|
+
trackedSessions:
|
|
115
|
+
typeof ck.trackedSessions === 'number'
|
|
116
|
+
? ck.trackedSessions
|
|
117
|
+
: undefined,
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
main,
|
|
124
|
+
fallbacks,
|
|
125
|
+
activeId: typeof raw.activeId === 'string' ? raw.activeId : undefined,
|
|
126
|
+
route:
|
|
127
|
+
typeof raw.route === 'string' ? raw.route : DEFAULT_SIDEBAR_STATE.route,
|
|
128
|
+
relay,
|
|
129
|
+
fastMode:
|
|
130
|
+
typeof raw.fastMode === 'boolean'
|
|
131
|
+
? raw.fastMode
|
|
132
|
+
: DEFAULT_SIDEBAR_STATE.fastMode,
|
|
133
|
+
cacheKeep,
|
|
134
|
+
lastUpdated: typeof raw.lastUpdated === 'number' ? raw.lastUpdated : 0,
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let writeChain: Promise<void> = Promise.resolve()
|
|
61
139
|
|
|
62
140
|
export async function getSidebarState(): Promise<SidebarState> {
|
|
63
141
|
try {
|
|
64
142
|
const raw = await readFile(getSidebarStateFile(), 'utf8')
|
|
65
|
-
return JSON.parse(raw)
|
|
143
|
+
return normalizeSidebarState(JSON.parse(raw))
|
|
66
144
|
} catch {
|
|
67
145
|
return DEFAULT_SIDEBAR_STATE
|
|
68
146
|
}
|
|
69
147
|
}
|
|
70
148
|
|
|
71
|
-
export async function setSidebarState(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
149
|
+
export async function setSidebarState(
|
|
150
|
+
state: SidebarState,
|
|
151
|
+
stateFile = getSidebarStateFile(),
|
|
152
|
+
): Promise<void> {
|
|
153
|
+
writeChain = writeChain
|
|
154
|
+
.then(async () => {
|
|
155
|
+
await mkdir(dirname(stateFile), { recursive: true })
|
|
156
|
+
await writeFile(stateFile, JSON.stringify(state), 'utf8')
|
|
157
|
+
})
|
|
158
|
+
.catch(() => {
|
|
159
|
+
// Best-effort — sidebar is non-critical
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
return writeChain
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export async function drainSidebarWrites(): Promise<void> {
|
|
166
|
+
return writeChain
|
|
79
167
|
}
|
|
80
168
|
|
|
81
169
|
// Resolve the currently-active account from activeId for the collapsed sidebar
|
|
@@ -92,7 +180,7 @@ export function resolveActiveAccount(state: SidebarState): {
|
|
|
92
180
|
// accounts out of state.fallbacks, so in normal operation every entry is
|
|
93
181
|
// enabled. Kept so this pure helper stays correct for any caller and is
|
|
94
182
|
// exercised directly by the unit tests.
|
|
95
|
-
const fallback = state.fallbacks
|
|
183
|
+
const fallback = state.fallbacks?.find(
|
|
96
184
|
(account) => account.enabled && account.id === activeId,
|
|
97
185
|
)
|
|
98
186
|
if (fallback) {
|
|
@@ -103,7 +191,7 @@ export function resolveActiveAccount(state: SidebarState): {
|
|
|
103
191
|
}
|
|
104
192
|
}
|
|
105
193
|
}
|
|
106
|
-
return { id: 'main', name: 'main', quota: state.main
|
|
194
|
+
return { id: 'main', name: 'main', quota: state.main?.quota ?? null }
|
|
107
195
|
}
|
|
108
196
|
|
|
109
197
|
export function getCollapsedQuotaSummary(quota: AccountQuota | null): {
|