@cortexkit/opencode-anthropic-auth 1.21.0 → 1.23.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/README.md +57 -12
- package/dist/billing-lineage.d.ts +51 -0
- package/dist/claustrum-enrollment-registry.d.ts +4 -0
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +89 -6
- package/dist/custody-dimensions.d.ts +36 -0
- package/dist/custody-enrollment.d.ts +14 -0
- package/dist/custody-live.d.ts +111 -0
- package/dist/custody-manifest-watcher.d.ts +16 -0
- package/dist/custody-mode.d.ts +186 -0
- package/dist/effort-history.d.ts +62 -0
- package/dist/fable-fallback.d.ts +6 -7
- package/dist/{index-w9d41yy9.js → index-0jfsxyn9.js} +1 -1
- package/dist/index-1fq7h6yd.js +430 -0
- package/dist/{index-y0khnbt6.js → index-1gr8v4fn.js} +1 -1
- package/dist/index-797pmamn.js +2 -0
- package/dist/{index-1db17bc2.js → index-8y2t4mwz.js} +2 -2
- package/dist/index-a5d6v3ba.js +5 -0
- package/dist/index-n96q8pks.js +2 -0
- package/dist/index-xxhyhp98.js +2 -0
- package/dist/index-xzbhzz0a.js +2 -0
- package/dist/index-z7gfdyv3.js +1 -0
- package/dist/index.js +28 -21
- package/dist/local-login.d.ts +64 -0
- package/dist/{logger-ftk4bg3p.js → logger-kk9vyem9.js} +1 -1
- package/dist/prime-manager-registry.d.ts +5 -1
- package/dist/rpc/notifications.d.ts +3 -3
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +23 -1
- package/dist/rpc/protocol.js +1 -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/rpc/server-registry.d.ts +10 -0
- package/dist/setup/activation.d.ts +7 -0
- package/dist/setup/claustrum.d.ts +26 -0
- package/dist/setup/command-runner.d.ts +2 -0
- package/dist/setup/command.d.ts +8 -0
- package/dist/setup/detect.d.ts +5 -0
- package/dist/setup/jsonc.d.ts +9 -0
- package/dist/setup/opencode-config.d.ts +18 -0
- package/dist/setup/paths.d.ts +15 -0
- package/dist/setup/pi.d.ts +8 -0
- package/dist/setup/process-fence.d.ts +14 -0
- package/dist/setup/types.d.ts +37 -0
- package/dist/sidebar-state.d.ts +5 -2
- package/dist/sidebar-state.js +1 -1
- package/dist/transform.d.ts +17 -1
- package/dist/tui/command-dialogs.d.ts +28 -9
- package/dist/tui-preferences.js +2 -2
- package/package.json +10 -5
- package/src/rpc/notifications.ts +28 -24
- package/src/rpc/protocol.ts +34 -1
- package/src/rpc/rpc-client.ts +1 -1
- package/src/rpc/rpc-server.ts +18 -5
- package/src/rpc/server-registry.ts +61 -0
- package/src/sidebar-state.ts +42 -3
- package/src/tui/command-dialogs.tsx +301 -97
- package/src/tui-compiled/rpc/protocol.ts +34 -1
- package/src/tui-compiled/rpc/rpc-client.ts +1 -1
- package/src/tui-compiled/sidebar-state.ts +42 -3
- package/src/tui-compiled/tui/command-dialogs.tsx +240 -70
- package/src/tui-compiled/tui.tsx +8 -3
- package/src/tui.tsx +18 -3
- package/dist/index-4nz423bt.js +0 -4
- package/dist/index-4x20896x.js +0 -2
- package/dist/index-wezdyxst.js +0 -2
- package/dist/index-yskwj5e6.js +0 -428
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
custodyStatusLabel,
|
|
4
|
+
type PrimeAccountStatus,
|
|
5
|
+
} from '@cortexkit/anthropic-auth-core'
|
|
3
6
|
import type { TuiPluginApi } from '@opencode-ai/plugin/tui'
|
|
7
|
+
import type { AccountDialogAccount } from '../rpc/protocol'
|
|
4
8
|
import type { OpenDialogPayload } from '../rpc/protocol.js'
|
|
5
9
|
import { formatPrimeCost, formatPrimeTime } from '../sidebar-state.js'
|
|
6
10
|
|
|
@@ -15,6 +19,27 @@ type KillswitchDialogConfig = {
|
|
|
15
19
|
accounts?: Record<string, Record<string, number>>
|
|
16
20
|
}
|
|
17
21
|
|
|
22
|
+
type TuiAccountDialogAccount = Omit<
|
|
23
|
+
AccountDialogAccount,
|
|
24
|
+
'vaultReauth' | 'custodyState'
|
|
25
|
+
> &
|
|
26
|
+
Partial<Pick<AccountDialogAccount, 'vaultReauth' | 'custodyState'>>
|
|
27
|
+
|
|
28
|
+
type TuiAccountDialogPayload = {
|
|
29
|
+
accounts: TuiAccountDialogAccount[]
|
|
30
|
+
claustrumDetection: string
|
|
31
|
+
custodyMode?: TuiCustodyMode
|
|
32
|
+
enrollmentStatus?: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type TuiCustodyMode = 'local' | 'claustrum' | `mismatch: ${string}`
|
|
36
|
+
|
|
37
|
+
type AccountDialogOption = {
|
|
38
|
+
title: string
|
|
39
|
+
value: string
|
|
40
|
+
description?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
18
43
|
export const PRIME_DIALOG_OPTIONS = [
|
|
19
44
|
{ title: 'Enable', value: 'on' },
|
|
20
45
|
{ title: 'Disable', value: 'off' },
|
|
@@ -48,26 +73,189 @@ export function buildKillswitchThresholdSeed(
|
|
|
48
73
|
return seedParts.join(' ')
|
|
49
74
|
}
|
|
50
75
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
function normalizeTuiCustodyMode(value: string): TuiCustodyMode {
|
|
77
|
+
return value === 'local' || value === 'claustrum'
|
|
78
|
+
? value
|
|
79
|
+
: `mismatch: ${value}`
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function normalizeAccountDialogPayload(
|
|
83
|
+
value: unknown,
|
|
84
|
+
): TuiAccountDialogPayload {
|
|
85
|
+
const payload =
|
|
86
|
+
value && typeof value === 'object' ? (value as Record<string, unknown>) : {}
|
|
87
|
+
const rawAccounts = Array.isArray(payload.accounts) ? payload.accounts : []
|
|
88
|
+
const accounts = rawAccounts.flatMap((value) => {
|
|
89
|
+
if (!value || typeof value !== 'object') return []
|
|
90
|
+
const account = value as Record<string, unknown>
|
|
91
|
+
const quotaPercent = account.quotaPercent
|
|
92
|
+
if (
|
|
93
|
+
typeof account.id !== 'string' ||
|
|
94
|
+
typeof account.label !== 'string' ||
|
|
95
|
+
(account.role !== 'main' && account.role !== 'fallback') ||
|
|
96
|
+
typeof account.enabled !== 'boolean' ||
|
|
97
|
+
(quotaPercent !== null &&
|
|
98
|
+
(typeof quotaPercent !== 'number' || !Number.isFinite(quotaPercent))) ||
|
|
99
|
+
(account.claustrumGate !== 'on' &&
|
|
100
|
+
account.claustrumGate !== 'off' &&
|
|
101
|
+
account.claustrumGate !== 'na') ||
|
|
102
|
+
typeof account.vaultServed !== 'boolean'
|
|
103
|
+
) {
|
|
104
|
+
return []
|
|
105
|
+
}
|
|
106
|
+
const normalized = {
|
|
107
|
+
id: account.id,
|
|
108
|
+
label: account.label,
|
|
109
|
+
role: account.role,
|
|
110
|
+
enabled: account.enabled,
|
|
111
|
+
quotaPercent,
|
|
112
|
+
...(typeof account.tierLabel === 'string' && {
|
|
113
|
+
tierLabel: account.tierLabel,
|
|
114
|
+
}),
|
|
115
|
+
claustrumGate: account.claustrumGate,
|
|
116
|
+
vaultServed: account.vaultServed,
|
|
117
|
+
} satisfies TuiAccountDialogAccount
|
|
118
|
+
const custodyState = account.custodyState
|
|
119
|
+
if (
|
|
120
|
+
(custodyState === 'na' ||
|
|
121
|
+
custodyState === 'off' ||
|
|
122
|
+
custodyState === 'on-vault-served' ||
|
|
123
|
+
custodyState === 'on-vault-reauth' ||
|
|
124
|
+
custodyState === 'on-cold') &&
|
|
125
|
+
typeof account.vaultReauth === 'boolean'
|
|
126
|
+
) {
|
|
127
|
+
return [
|
|
128
|
+
{
|
|
129
|
+
...normalized,
|
|
130
|
+
custodyState,
|
|
131
|
+
vaultReauth: account.vaultReauth,
|
|
132
|
+
},
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
return [normalized]
|
|
136
|
+
})
|
|
137
|
+
const custodyMode: TuiCustodyMode | undefined =
|
|
138
|
+
payload.custodyModeKnown === true && typeof payload.custodyMode === 'string'
|
|
139
|
+
? normalizeTuiCustodyMode(payload.custodyMode)
|
|
140
|
+
: undefined
|
|
141
|
+
return {
|
|
142
|
+
accounts,
|
|
143
|
+
claustrumDetection:
|
|
144
|
+
typeof payload.claustrumDetection === 'string'
|
|
145
|
+
? payload.claustrumDetection
|
|
146
|
+
: 'unknown',
|
|
147
|
+
...(custodyMode && { custodyMode }),
|
|
148
|
+
...(typeof payload.enrollmentStatus === 'string' &&
|
|
149
|
+
payload.enrollmentStatus.length <= 2_000 && {
|
|
150
|
+
enrollmentStatus: payload.enrollmentStatus,
|
|
151
|
+
}),
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function buildAccountDialogOption(account: TuiAccountDialogAccount) {
|
|
59
156
|
const pct =
|
|
60
157
|
account.quotaPercent != null
|
|
61
158
|
? ` ${Math.round(account.quotaPercent)}%`
|
|
62
159
|
: ' \u2013%'
|
|
63
160
|
const status = !account.enabled ? ' (disabled)' : ''
|
|
161
|
+
const custody = account.custodyState
|
|
162
|
+
? account.custodyState === 'na'
|
|
163
|
+
? undefined
|
|
164
|
+
: custodyStatusLabel(account.custodyState).replace(
|
|
165
|
+
' (OpenCode managed)',
|
|
166
|
+
'',
|
|
167
|
+
)
|
|
168
|
+
: undefined
|
|
64
169
|
return {
|
|
65
|
-
title: `${account.label} [${account.role}]${status}${pct}`,
|
|
170
|
+
title: `${account.label} [${account.role}]${status}${pct}${custody ? ` · custody ${custody}` : ''}`,
|
|
66
171
|
value: account.id,
|
|
67
172
|
...(account.tierLabel && { description: account.tierLabel }),
|
|
68
173
|
}
|
|
69
174
|
}
|
|
70
175
|
|
|
176
|
+
export function buildManageAccountOptions(account: TuiAccountDialogAccount) {
|
|
177
|
+
const options: AccountDialogOption[] = []
|
|
178
|
+
const toggleLabel = account.enabled ? 'Disable' : 'Enable'
|
|
179
|
+
options.push({
|
|
180
|
+
title: toggleLabel,
|
|
181
|
+
value: account.enabled ? 'disable' : 'enable',
|
|
182
|
+
description: account.enabled
|
|
183
|
+
? 'Stop using this fallback account'
|
|
184
|
+
: 'Allow this fallback account to be used',
|
|
185
|
+
})
|
|
186
|
+
options.push({
|
|
187
|
+
title: 'Move up',
|
|
188
|
+
value: 'move-up',
|
|
189
|
+
description: 'Higher priority in fallback order',
|
|
190
|
+
})
|
|
191
|
+
options.push({
|
|
192
|
+
title: 'Move down',
|
|
193
|
+
value: 'move-down',
|
|
194
|
+
description: 'Lower priority in fallback order',
|
|
195
|
+
})
|
|
196
|
+
options.push({
|
|
197
|
+
title: 'Remove\u2026',
|
|
198
|
+
value: 'remove',
|
|
199
|
+
description: 'Delete this account permanently',
|
|
200
|
+
})
|
|
201
|
+
options.push({ title: 'Back', value: 'back' })
|
|
202
|
+
return options
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export function buildAccountDialogL1(value: unknown): {
|
|
206
|
+
header: string
|
|
207
|
+
options: AccountDialogOption[]
|
|
208
|
+
enrollmentStatus?: string
|
|
209
|
+
modeAction?: { command: 'claude-account'; arguments: 'local' | 'claustrum' }
|
|
210
|
+
} {
|
|
211
|
+
const payload = normalizeAccountDialogPayload(value)
|
|
212
|
+
const modeAction =
|
|
213
|
+
payload.custodyMode === 'local' || payload.custodyMode === 'claustrum'
|
|
214
|
+
? {
|
|
215
|
+
command: 'claude-account' as const,
|
|
216
|
+
arguments:
|
|
217
|
+
payload.custodyMode === 'local'
|
|
218
|
+
? ('claustrum' as const)
|
|
219
|
+
: ('local' as const),
|
|
220
|
+
}
|
|
221
|
+
: undefined
|
|
222
|
+
return {
|
|
223
|
+
header: payload.custodyMode
|
|
224
|
+
? `Custody mode: ${payload.custodyMode}`
|
|
225
|
+
: 'Custody mode: unavailable from older server',
|
|
226
|
+
options: [
|
|
227
|
+
...(modeAction
|
|
228
|
+
? [
|
|
229
|
+
{
|
|
230
|
+
title:
|
|
231
|
+
payload.custodyMode === 'local'
|
|
232
|
+
? 'Use Claustrum custody'
|
|
233
|
+
: 'Use local custody',
|
|
234
|
+
value: '__custody-mode__',
|
|
235
|
+
},
|
|
236
|
+
]
|
|
237
|
+
: []),
|
|
238
|
+
{
|
|
239
|
+
title: 'Add account…',
|
|
240
|
+
value: '__add__',
|
|
241
|
+
description: 'Add an API key or OAuth fallback account',
|
|
242
|
+
},
|
|
243
|
+
...payload.accounts.map(buildAccountDialogOption),
|
|
244
|
+
],
|
|
245
|
+
...(payload.enrollmentStatus && {
|
|
246
|
+
enrollmentStatus: payload.enrollmentStatus,
|
|
247
|
+
}),
|
|
248
|
+
...(modeAction && { modeAction }),
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export function retainAccountDialogProjection(
|
|
253
|
+
current: Record<string, unknown>,
|
|
254
|
+
incoming: Record<string, unknown>,
|
|
255
|
+
): Record<string, unknown> {
|
|
256
|
+
return Array.isArray(incoming.accounts) ? incoming : current
|
|
257
|
+
}
|
|
258
|
+
|
|
71
259
|
function showText(api: TuiPluginApi, text: string) {
|
|
72
260
|
api.ui.dialog.setSize('xlarge')
|
|
73
261
|
api.ui.dialog.replace(() => (
|
|
@@ -100,6 +288,8 @@ export function buildPrimeStatusRows(accounts: PrimeAccountStatus[]): string[] {
|
|
|
100
288
|
const time = formatPrimeTime(account.lastPrimedAt)
|
|
101
289
|
if (account.lastResult === 'error') {
|
|
102
290
|
rows.push(`${account.label} \u00b7 primed ${time} err`)
|
|
291
|
+
} else if (account.lastResult === 'skipped') {
|
|
292
|
+
rows.push(`${account.label} \u00b7 primed ${time} skipped`)
|
|
103
293
|
} else {
|
|
104
294
|
rows.push(`${account.label} \u00b7 primed ${time} \u2713`)
|
|
105
295
|
}
|
|
@@ -378,22 +568,17 @@ export function openCommandDialog(
|
|
|
378
568
|
}
|
|
379
569
|
|
|
380
570
|
if (payload.command === 'claude-account') {
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
label: string
|
|
385
|
-
role: string
|
|
386
|
-
enabled: boolean
|
|
387
|
-
quotaPercent: number | null
|
|
388
|
-
tierLabel?: string
|
|
389
|
-
}>) ?? []
|
|
571
|
+
let accountKnobs: Record<string, unknown> = payload.knobs
|
|
572
|
+
const accounts = normalizeAccountDialogPayload(accountKnobs).accounts
|
|
573
|
+
let statusMessage: { text: string; error?: boolean } | undefined
|
|
390
574
|
|
|
391
575
|
const updateAccounts = (r: {
|
|
392
576
|
text: string
|
|
393
577
|
knobs: Record<string, unknown>
|
|
394
578
|
}) => {
|
|
395
|
-
|
|
396
|
-
|
|
579
|
+
accountKnobs = retainAccountDialogProjection(accountKnobs, r.knobs)
|
|
580
|
+
const updated = normalizeAccountDialogPayload(accountKnobs).accounts
|
|
581
|
+
if (updated.length > 0) {
|
|
397
582
|
accounts.length = 0
|
|
398
583
|
accounts.push(...updated)
|
|
399
584
|
}
|
|
@@ -401,44 +586,79 @@ export function openCommandDialog(
|
|
|
401
586
|
|
|
402
587
|
const buildL1 = () => {
|
|
403
588
|
const DialogSelect = api.ui.DialogSelect<string>
|
|
404
|
-
const
|
|
405
|
-
title: string
|
|
406
|
-
value: string
|
|
407
|
-
description?: string
|
|
408
|
-
}> = [
|
|
409
|
-
{
|
|
410
|
-
title: 'Add account\u2026',
|
|
411
|
-
value: '__add__',
|
|
412
|
-
description: 'Add an API key or OAuth fallback account',
|
|
413
|
-
},
|
|
414
|
-
...accounts.map(buildAccountDialogOption),
|
|
415
|
-
]
|
|
589
|
+
const l1 = buildAccountDialogL1({ ...accountKnobs, accounts })
|
|
416
590
|
api.ui.dialog.setSize('xlarge')
|
|
417
591
|
api.ui.dialog.replace(() => (
|
|
418
|
-
<
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
592
|
+
<box flexDirection='column' padding={1} width='100%'>
|
|
593
|
+
<text>{`Claustrum: ${normalizeAccountDialogPayload(accountKnobs).claustrumDetection}`}</text>
|
|
594
|
+
<text>{l1.header}</text>
|
|
595
|
+
{l1.enrollmentStatus && (
|
|
596
|
+
<box marginTop={1}>
|
|
597
|
+
<text>{l1.enrollmentStatus}</text>
|
|
598
|
+
</box>
|
|
599
|
+
)}
|
|
600
|
+
{statusMessage && (
|
|
601
|
+
<box marginTop={1}>
|
|
602
|
+
<text fg={statusMessage.error ? '#ef4444' : '#22c55e'}>
|
|
603
|
+
{statusMessage.text}
|
|
604
|
+
</text>
|
|
605
|
+
</box>
|
|
606
|
+
)}
|
|
607
|
+
<box marginTop={1}>
|
|
608
|
+
<DialogSelect
|
|
609
|
+
title='Claude accounts'
|
|
610
|
+
options={l1.options}
|
|
611
|
+
onSelect={(option) => {
|
|
612
|
+
if (option.value === '__add__') {
|
|
613
|
+
statusMessage = undefined
|
|
614
|
+
openAddType()
|
|
615
|
+
return
|
|
616
|
+
}
|
|
617
|
+
if (option.value === '__custody-mode__' && l1.modeAction) {
|
|
618
|
+
void apply(l1.modeAction.command, l1.modeAction.arguments)
|
|
619
|
+
.then((r) => {
|
|
620
|
+
const isRefusalOrError =
|
|
621
|
+
r.text.includes('refused') ||
|
|
622
|
+
r.text.includes('unavailable') ||
|
|
623
|
+
r.text.includes('failed') ||
|
|
624
|
+
r.text.includes('Error') ||
|
|
625
|
+
r.text.includes('error')
|
|
626
|
+
if (isRefusalOrError) {
|
|
627
|
+
statusMessage = { text: r.text, error: true }
|
|
628
|
+
} else {
|
|
629
|
+
statusMessage = { text: r.text, error: false }
|
|
630
|
+
api.ui.toast({ message: r.text })
|
|
631
|
+
}
|
|
632
|
+
updateAccounts(r)
|
|
633
|
+
buildL1()
|
|
634
|
+
})
|
|
635
|
+
.catch((err) => {
|
|
636
|
+
const msg =
|
|
637
|
+
err instanceof Error ? err.message : String(err)
|
|
638
|
+
statusMessage = { text: `Error: ${msg}`, error: true }
|
|
639
|
+
buildL1()
|
|
640
|
+
})
|
|
641
|
+
return
|
|
642
|
+
}
|
|
643
|
+
statusMessage = undefined
|
|
644
|
+
const account = accounts.find((a) => a.id === option.value)
|
|
645
|
+
if (!account) return
|
|
646
|
+
if (account.role === 'main') {
|
|
647
|
+
const pct =
|
|
648
|
+
account.quotaPercent != null
|
|
649
|
+
? ` ${Math.round(account.quotaPercent)}%`
|
|
650
|
+
: ' \u2013%'
|
|
651
|
+
showText(
|
|
652
|
+
api,
|
|
653
|
+
`${account.label}\nRole: main (read-only)\nQuota:${pct}`,
|
|
654
|
+
)
|
|
655
|
+
return
|
|
656
|
+
}
|
|
657
|
+
openManage(account, false)
|
|
658
|
+
}}
|
|
659
|
+
/>
|
|
660
|
+
</box>
|
|
661
|
+
</box>
|
|
442
662
|
))
|
|
443
663
|
}
|
|
444
664
|
|
|
@@ -738,37 +958,9 @@ export function openCommandDialog(
|
|
|
738
958
|
const DialogConfirm = api.ui.DialogConfirm
|
|
739
959
|
api.ui.dialog.setSize('xlarge')
|
|
740
960
|
|
|
741
|
-
const options
|
|
742
|
-
title:
|
|
743
|
-
|
|
744
|
-
description?: string
|
|
745
|
-
}> = []
|
|
746
|
-
if (!isMain) {
|
|
747
|
-
const toggleLabel = account.enabled ? 'Disable' : 'Enable'
|
|
748
|
-
options.push({
|
|
749
|
-
title: toggleLabel,
|
|
750
|
-
value: account.enabled ? 'disable' : 'enable',
|
|
751
|
-
description: account.enabled
|
|
752
|
-
? 'Stop using this fallback account'
|
|
753
|
-
: 'Allow this fallback account to be used',
|
|
754
|
-
})
|
|
755
|
-
options.push({
|
|
756
|
-
title: 'Move up',
|
|
757
|
-
value: 'move-up',
|
|
758
|
-
description: 'Higher priority in fallback order',
|
|
759
|
-
})
|
|
760
|
-
options.push({
|
|
761
|
-
title: 'Move down',
|
|
762
|
-
value: 'move-down',
|
|
763
|
-
description: 'Lower priority in fallback order',
|
|
764
|
-
})
|
|
765
|
-
options.push({
|
|
766
|
-
title: 'Remove\u2026',
|
|
767
|
-
value: 'remove',
|
|
768
|
-
description: 'Delete this account permanently',
|
|
769
|
-
})
|
|
770
|
-
}
|
|
771
|
-
options.push({ title: 'Back', value: 'back' })
|
|
961
|
+
const options = isMain
|
|
962
|
+
? [{ title: 'Back', value: 'back' }]
|
|
963
|
+
: buildManageAccountOptions(account)
|
|
772
964
|
|
|
773
965
|
api.ui.dialog.replace(() => (
|
|
774
966
|
<DialogSelect
|
|
@@ -786,13 +978,18 @@ export function openCommandDialog(
|
|
|
786
978
|
title={`Remove ${account.label}?`}
|
|
787
979
|
message={`Are you sure you want to remove the fallback account "${account.label}"?`}
|
|
788
980
|
onConfirm={() => {
|
|
789
|
-
void apply('claude-account', `remove ${account.id}`)
|
|
790
|
-
(r) => {
|
|
981
|
+
void apply('claude-account', `remove ${account.id}`)
|
|
982
|
+
.then((r) => {
|
|
791
983
|
api.ui.toast({ message: r.text })
|
|
792
984
|
updateAccounts(r)
|
|
793
985
|
buildL1()
|
|
794
|
-
}
|
|
795
|
-
|
|
986
|
+
})
|
|
987
|
+
.catch((err) => {
|
|
988
|
+
const msg =
|
|
989
|
+
err instanceof Error ? err.message : String(err)
|
|
990
|
+
statusMessage = { text: `Error: ${msg}`, error: true }
|
|
991
|
+
buildL1()
|
|
992
|
+
})
|
|
796
993
|
}}
|
|
797
994
|
onCancel={() => openManage(account, isMain)}
|
|
798
995
|
/>
|
|
@@ -800,18 +997,25 @@ export function openCommandDialog(
|
|
|
800
997
|
return
|
|
801
998
|
}
|
|
802
999
|
|
|
803
|
-
|
|
804
|
-
|
|
1000
|
+
const args = `${option.value} ${account.id}`
|
|
1001
|
+
void apply('claude-account', args)
|
|
1002
|
+
.then((r) => {
|
|
805
1003
|
api.ui.toast({ message: r.text })
|
|
806
1004
|
updateAccounts(r)
|
|
807
|
-
const updatedList =
|
|
1005
|
+
const updatedList = normalizeAccountDialogPayload(
|
|
1006
|
+
r.knobs,
|
|
1007
|
+
).accounts
|
|
808
1008
|
const refreshed =
|
|
809
1009
|
(updatedList && updatedList.length > 0
|
|
810
1010
|
? updatedList.find((a) => a.id === account.id)
|
|
811
1011
|
: undefined) ?? account
|
|
812
1012
|
openManage(refreshed, isMain)
|
|
813
|
-
}
|
|
814
|
-
|
|
1013
|
+
})
|
|
1014
|
+
.catch((err) => {
|
|
1015
|
+
const msg = err instanceof Error ? err.message : String(err)
|
|
1016
|
+
statusMessage = { text: `Error: ${msg}`, error: true }
|
|
1017
|
+
buildL1()
|
|
1018
|
+
})
|
|
815
1019
|
}}
|
|
816
1020
|
/>
|
|
817
1021
|
))
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ClaustrumEnrollmentStatus } from '@cortexkit/anthropic-auth-core'
|
|
2
|
+
|
|
1
3
|
export const COMMAND_MODAL_NAMES = [
|
|
2
4
|
'claude-account',
|
|
3
5
|
'claude-cache',
|
|
@@ -14,6 +16,37 @@ export const COMMAND_MODAL_NAMES = [
|
|
|
14
16
|
|
|
15
17
|
export type CommandModalName = (typeof COMMAND_MODAL_NAMES)[number]
|
|
16
18
|
|
|
19
|
+
export interface AccountDialogAccount {
|
|
20
|
+
id: string
|
|
21
|
+
label: string
|
|
22
|
+
role: 'main' | 'fallback'
|
|
23
|
+
enabled: boolean
|
|
24
|
+
quotaPercent: number | null
|
|
25
|
+
tierLabel?: string
|
|
26
|
+
claustrumGate: 'on' | 'off' | 'na'
|
|
27
|
+
vaultServed: boolean
|
|
28
|
+
vaultReauth: boolean
|
|
29
|
+
custodyState:
|
|
30
|
+
| 'na'
|
|
31
|
+
| 'off'
|
|
32
|
+
| 'on-vault-served'
|
|
33
|
+
| 'on-vault-reauth'
|
|
34
|
+
| 'on-cold'
|
|
35
|
+
| 'unknown-identity'
|
|
36
|
+
| 'on-identity-mismatch'
|
|
37
|
+
| 'on-corrupt-binding'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface AccountDialogKnobs {
|
|
41
|
+
accounts: AccountDialogAccount[]
|
|
42
|
+
claustrumDetection: string
|
|
43
|
+
custodyMode?: 'local' | 'claustrum'
|
|
44
|
+
custodyModeKnown?: boolean
|
|
45
|
+
enrollmentStatus?: string
|
|
46
|
+
claustrumEnrollment?: ClaustrumEnrollmentStatus
|
|
47
|
+
[key: string]: unknown
|
|
48
|
+
}
|
|
49
|
+
|
|
17
50
|
export interface OpenDialogPayload {
|
|
18
51
|
command: CommandModalName
|
|
19
52
|
text: string
|
|
@@ -24,7 +57,7 @@ export interface RpcNotification {
|
|
|
24
57
|
id: number
|
|
25
58
|
type: 'open-dialog'
|
|
26
59
|
payload: OpenDialogPayload
|
|
27
|
-
sessionId
|
|
60
|
+
sessionId: string
|
|
28
61
|
}
|
|
29
62
|
|
|
30
63
|
export interface ApplyRequest {
|
|
@@ -4,7 +4,7 @@ import type { ApplyRequest, ApplyResult, RpcNotification } from './protocol'
|
|
|
4
4
|
export interface RpcClient {
|
|
5
5
|
pending: (
|
|
6
6
|
lastReceivedId: number,
|
|
7
|
-
sessionId
|
|
7
|
+
sessionId: string,
|
|
8
8
|
) => Promise<RpcNotification[]>
|
|
9
9
|
apply: (request: ApplyRequest) => Promise<ApplyResult>
|
|
10
10
|
}
|
|
@@ -34,6 +34,18 @@ 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
|
|
39
|
+
// A gate alone does not prove the sidecar can serve a request.
|
|
40
|
+
vaultServed?: boolean
|
|
41
|
+
custodyState?:
|
|
42
|
+
| 'off'
|
|
43
|
+
| 'on-vault-served'
|
|
44
|
+
| 'on-vault-reauth'
|
|
45
|
+
| 'on-cold'
|
|
46
|
+
| 'unknown-identity'
|
|
47
|
+
| 'on-identity-mismatch'
|
|
48
|
+
| 'on-corrupt-binding'
|
|
37
49
|
tierLabel?: string
|
|
38
50
|
}
|
|
39
51
|
|
|
@@ -57,7 +69,7 @@ export interface PrimeSidebarAccountState {
|
|
|
57
69
|
label: string
|
|
58
70
|
nextDueAt?: number | null
|
|
59
71
|
lastPrimedAt?: number | null
|
|
60
|
-
lastResult?: 'ok' | 'error'
|
|
72
|
+
lastResult?: 'ok' | 'error' | 'skipped'
|
|
61
73
|
usage?: PrimeUsageCounters
|
|
62
74
|
estimatedCostUsd?: number
|
|
63
75
|
}
|
|
@@ -178,7 +190,11 @@ function normalizePrimeAccount(
|
|
|
178
190
|
} else if (isFiniteNumber(value.lastPrimedAt)) {
|
|
179
191
|
account.lastPrimedAt = value.lastPrimedAt
|
|
180
192
|
}
|
|
181
|
-
if (
|
|
193
|
+
if (
|
|
194
|
+
value.lastResult === 'ok' ||
|
|
195
|
+
value.lastResult === 'error' ||
|
|
196
|
+
value.lastResult === 'skipped'
|
|
197
|
+
) {
|
|
182
198
|
account.lastResult = value.lastResult
|
|
183
199
|
}
|
|
184
200
|
const usage = normalizePrimeUsage(value.usage)
|
|
@@ -335,6 +351,12 @@ export function normalizeSidebarState(raw: unknown): SidebarState {
|
|
|
335
351
|
enabled: typeof entry.enabled === 'boolean' ? entry.enabled : false,
|
|
336
352
|
needsReauth:
|
|
337
353
|
typeof entry.needsReauth === 'boolean' ? entry.needsReauth : false,
|
|
354
|
+
...(entry.vaultReauth === true && { vaultReauth: true }),
|
|
355
|
+
...(entry.vaultServed === true && { vaultServed: true }),
|
|
356
|
+
...(typeof entry.custodyState === 'string' && {
|
|
357
|
+
custodyState:
|
|
358
|
+
entry.custodyState as SidebarAccountState['custodyState'],
|
|
359
|
+
}),
|
|
338
360
|
tierLabel:
|
|
339
361
|
typeof entry.tierLabel === 'string' && entry.tierLabel.trim()
|
|
340
362
|
? entry.tierLabel.trim()
|
|
@@ -715,6 +737,8 @@ export async function setSidebarState(
|
|
|
715
737
|
lastUpdated: Math.max(current.lastUpdated, state.lastUpdated),
|
|
716
738
|
}
|
|
717
739
|
}
|
|
740
|
+
// The state file is a cross-process artifact; future account fields must fail closed.
|
|
741
|
+
stateToWrite = normalizeSidebarState(stateToWrite)
|
|
718
742
|
result = await writeSidebarStateAtomic(
|
|
719
743
|
stateFile,
|
|
720
744
|
stateToWrite,
|
|
@@ -795,13 +819,25 @@ export function formatScopedQuotaLabel(title: string) {
|
|
|
795
819
|
}
|
|
796
820
|
|
|
797
821
|
/**
|
|
798
|
-
* Pretty label for a recoverable-refusal source model (Fable 5 or Opus 5).
|
|
822
|
+
* Pretty label for a recoverable-refusal source model (Fable 5/5.1 or Opus 5).
|
|
799
823
|
* Falls back to the raw id for unrecognized ids so the sidebar never goes
|
|
800
824
|
* blank on a future model that has not yet been cataloged here.
|
|
801
825
|
*/
|
|
802
826
|
export function formatFallbackModelLabel(modelId: string | undefined): string {
|
|
827
|
+
if (
|
|
828
|
+
modelId === 'claude-mythos-5-1' ||
|
|
829
|
+
modelId?.startsWith('claude-mythos-5-1-')
|
|
830
|
+
)
|
|
831
|
+
return 'Mythos 5.1'
|
|
832
|
+
if (
|
|
833
|
+
modelId === 'claude-fable-5-1' ||
|
|
834
|
+
modelId?.startsWith('claude-fable-5-1-')
|
|
835
|
+
)
|
|
836
|
+
return 'Fable 5.1'
|
|
803
837
|
if (modelId === 'claude-fable-5' || modelId?.startsWith('claude-fable-5-'))
|
|
804
838
|
return 'Fable 5'
|
|
839
|
+
if (modelId === 'claude-opus-5-5' || modelId?.startsWith('claude-opus-5-5-'))
|
|
840
|
+
return 'Opus 5.5'
|
|
805
841
|
if (modelId === 'claude-opus-5' || modelId?.startsWith('claude-opus-5-'))
|
|
806
842
|
return 'Opus 5'
|
|
807
843
|
if (modelId === 'claude-opus-4-8' || modelId?.startsWith('claude-opus-4-8-'))
|
|
@@ -829,6 +865,9 @@ export function formatPrimeAccountValue(account: PrimeSidebarAccountState): {
|
|
|
829
865
|
if (account.lastResult === 'error') {
|
|
830
866
|
return { text: 'err', hasError: true }
|
|
831
867
|
}
|
|
868
|
+
if (account.lastResult === 'skipped') {
|
|
869
|
+
return { text: 'skip', hasError: false }
|
|
870
|
+
}
|
|
832
871
|
if (account.nextDueAt && account.nextDueAt > Date.now()) {
|
|
833
872
|
return { text: formatPrimeTime(account.nextDueAt), hasError: false }
|
|
834
873
|
}
|