@cortexkit/opencode-anthropic-auth 1.12.2 → 1.13.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 +8 -5
- package/dist/cli.js +5 -5
- package/dist/{index-ptdkq8gx.js → index-1gc9eney.js} +1 -1
- package/dist/index-9053h96k.js +417 -0
- package/dist/{index-9rxvhx0b.js → index-97vmbv5w.js} +1 -1
- package/dist/index-bk5avdcz.js +2 -0
- package/dist/{index-ggyzz0xr.js → index-ha0gz07d.js} +1 -1
- package/dist/{index-z86v5q5a.js → index-se4sd5kz.js} +1 -1
- package/dist/index.d.ts +37 -0
- package/dist/index.js +11 -11
- package/dist/{logger-59cepv7b.js → logger-sg9wxpvj.js} +1 -1
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state.d.ts +9 -0
- package/dist/sidebar-state.js +1 -1
- package/dist/tui/command-dialogs.d.ts +6 -0
- package/dist/tui-preferences.js +1 -1
- package/package.json +2 -2
- package/src/sidebar-state.ts +92 -5
- package/src/tui/command-dialogs.tsx +29 -19
- package/src/tui.tsx +26 -1
- package/dist/index-67j80sm1.js +0 -417
- package/dist/index-erkja50x.js +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cortexkit/opencode-anthropic-auth",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@opencode-ai/plugin": "*"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@cortexkit/anthropic-auth-core": "1.
|
|
61
|
+
"@cortexkit/anthropic-auth-core": "1.13.0",
|
|
62
62
|
"@opentui/core": ">=0.4.2",
|
|
63
63
|
"@opentui/solid": ">=0.4.2",
|
|
64
64
|
"jsonc-parser": "^3.3.1",
|
package/src/sidebar-state.ts
CHANGED
|
@@ -4,9 +4,17 @@ export interface QuotaWindow {
|
|
|
4
4
|
resetsAt?: string
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
export interface ScopedQuotaWindow extends QuotaWindow {
|
|
8
|
+
id: string
|
|
9
|
+
title: string
|
|
10
|
+
modelId?: string
|
|
11
|
+
modelName: string
|
|
12
|
+
}
|
|
13
|
+
|
|
7
14
|
export interface AccountQuota {
|
|
8
15
|
five_hour?: QuotaWindow
|
|
9
16
|
seven_day?: QuotaWindow
|
|
17
|
+
scoped?: ScopedQuotaWindow[]
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
export interface SidebarAccountState {
|
|
@@ -65,13 +73,67 @@ function isRecord(v: unknown): v is Record<string, unknown> {
|
|
|
65
73
|
return v !== null && typeof v === 'object' && !Array.isArray(v)
|
|
66
74
|
}
|
|
67
75
|
|
|
76
|
+
function normalizeQuotaWindow(value: unknown): QuotaWindow | undefined {
|
|
77
|
+
if (!isRecord(value)) return undefined
|
|
78
|
+
const usedPercent = Number(value.usedPercent)
|
|
79
|
+
const remainingPercent = Number(value.remainingPercent)
|
|
80
|
+
if (!Number.isFinite(usedPercent) || !Number.isFinite(remainingPercent)) {
|
|
81
|
+
return undefined
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
usedPercent,
|
|
85
|
+
remainingPercent,
|
|
86
|
+
resetsAt: typeof value.resetsAt === 'string' ? value.resetsAt : undefined,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function normalizeAccountQuota(value: unknown): AccountQuota | null {
|
|
91
|
+
if (!isRecord(value)) return null
|
|
92
|
+
const quota: AccountQuota = {}
|
|
93
|
+
const fiveHour = normalizeQuotaWindow(value.five_hour)
|
|
94
|
+
const sevenDay = normalizeQuotaWindow(value.seven_day)
|
|
95
|
+
if (fiveHour) quota.five_hour = fiveHour
|
|
96
|
+
if (sevenDay) quota.seven_day = sevenDay
|
|
97
|
+
|
|
98
|
+
if (Array.isArray(value.scoped)) {
|
|
99
|
+
const scoped = value.scoped
|
|
100
|
+
.map((entry): ScopedQuotaWindow | undefined => {
|
|
101
|
+
if (!isRecord(entry)) return undefined
|
|
102
|
+
const window = normalizeQuotaWindow(entry)
|
|
103
|
+
if (!window) return undefined
|
|
104
|
+
if (typeof entry.id !== 'string' || !entry.id.trim()) return undefined
|
|
105
|
+
if (typeof entry.title !== 'string' || !entry.title.trim()) {
|
|
106
|
+
return undefined
|
|
107
|
+
}
|
|
108
|
+
if (typeof entry.modelName !== 'string' || !entry.modelName.trim()) {
|
|
109
|
+
return undefined
|
|
110
|
+
}
|
|
111
|
+
const modelId =
|
|
112
|
+
typeof entry.modelId === 'string' && entry.modelId.trim()
|
|
113
|
+
? entry.modelId.trim()
|
|
114
|
+
: undefined
|
|
115
|
+
return {
|
|
116
|
+
...window,
|
|
117
|
+
id: entry.id.trim(),
|
|
118
|
+
title: entry.title.trim(),
|
|
119
|
+
...(modelId && { modelId }),
|
|
120
|
+
modelName: entry.modelName.trim(),
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
.filter((entry): entry is ScopedQuotaWindow => entry != null)
|
|
124
|
+
if (scoped.length) quota.scoped = scoped
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return Object.keys(quota).length ? quota : null
|
|
128
|
+
}
|
|
129
|
+
|
|
68
130
|
export function normalizeSidebarState(raw: unknown): SidebarState {
|
|
69
131
|
if (!isRecord(raw)) return { ...DEFAULT_SIDEBAR_STATE }
|
|
70
132
|
|
|
71
133
|
const main: SidebarState['main'] = { quota: null }
|
|
72
134
|
if (isRecord(raw.main)) {
|
|
73
135
|
const m = raw.main
|
|
74
|
-
main.quota =
|
|
136
|
+
main.quota = normalizeAccountQuota(m.quota)
|
|
75
137
|
if (typeof m.quotaBackedOff === 'boolean')
|
|
76
138
|
main.quotaBackedOff = m.quotaBackedOff
|
|
77
139
|
if (typeof m.quotaBackoffUntil === 'number')
|
|
@@ -89,7 +151,7 @@ export function normalizeSidebarState(raw: unknown): SidebarState {
|
|
|
89
151
|
.map((entry) => ({
|
|
90
152
|
id: entry.id as string,
|
|
91
153
|
label: typeof entry.label === 'string' ? entry.label : undefined,
|
|
92
|
-
quota:
|
|
154
|
+
quota: normalizeAccountQuota(entry.quota),
|
|
93
155
|
enabled: typeof entry.enabled === 'boolean' ? entry.enabled : false,
|
|
94
156
|
needsReauth:
|
|
95
157
|
typeof entry.needsReauth === 'boolean' ? entry.needsReauth : false,
|
|
@@ -194,21 +256,46 @@ export function resolveActiveAccount(state: SidebarState): {
|
|
|
194
256
|
return { id: 'main', name: 'main', quota: state.main?.quota ?? null }
|
|
195
257
|
}
|
|
196
258
|
|
|
259
|
+
export function formatScopedQuotaLabel(title: string) {
|
|
260
|
+
const label = title.replace(/\s+only$/i, '').trim()
|
|
261
|
+
return /^fable$/i.test(label) ? 'Fa' : label
|
|
262
|
+
}
|
|
263
|
+
|
|
197
264
|
export function getCollapsedQuotaSummary(quota: AccountQuota | null): {
|
|
198
265
|
fiveHourUsedPercent: number | null
|
|
199
266
|
sevenDayUsedPercent: number | null
|
|
267
|
+
scopedUsedPercents: number[]
|
|
200
268
|
text: string | null
|
|
201
269
|
} {
|
|
202
270
|
const fiveHourUsedPercent = quota?.five_hour?.usedPercent ?? null
|
|
203
271
|
const sevenDayUsedPercent = quota?.seven_day?.usedPercent ?? null
|
|
204
|
-
|
|
205
|
-
|
|
272
|
+
const scoped = quota?.scoped ?? []
|
|
273
|
+
const scopedUsedPercents = scoped.map((window) => window.usedPercent)
|
|
274
|
+
if (
|
|
275
|
+
fiveHourUsedPercent == null &&
|
|
276
|
+
sevenDayUsedPercent == null &&
|
|
277
|
+
scoped.length === 0
|
|
278
|
+
) {
|
|
279
|
+
return {
|
|
280
|
+
fiveHourUsedPercent,
|
|
281
|
+
sevenDayUsedPercent,
|
|
282
|
+
scopedUsedPercents,
|
|
283
|
+
text: null,
|
|
284
|
+
}
|
|
206
285
|
}
|
|
207
286
|
|
|
208
287
|
return {
|
|
209
288
|
fiveHourUsedPercent,
|
|
210
289
|
sevenDayUsedPercent,
|
|
211
|
-
|
|
290
|
+
scopedUsedPercents,
|
|
291
|
+
text: [
|
|
292
|
+
`5h: ${fiveHourUsedPercent == null ? '—' : `${Math.round(fiveHourUsedPercent)}%`}`,
|
|
293
|
+
`7d: ${sevenDayUsedPercent == null ? '—' : `${Math.round(sevenDayUsedPercent)}%`}`,
|
|
294
|
+
...scoped.map(
|
|
295
|
+
(window) =>
|
|
296
|
+
`${formatScopedQuotaLabel(window.title)}: ${Math.round(window.usedPercent)}%`,
|
|
297
|
+
),
|
|
298
|
+
].join(' '),
|
|
212
299
|
}
|
|
213
300
|
}
|
|
214
301
|
|
|
@@ -7,6 +7,31 @@ type ApplyFn = (
|
|
|
7
7
|
args: string,
|
|
8
8
|
) => Promise<{ text: string; knobs: Record<string, unknown> }>
|
|
9
9
|
|
|
10
|
+
type KillswitchDialogConfig = {
|
|
11
|
+
enabled?: boolean
|
|
12
|
+
main?: Record<string, number>
|
|
13
|
+
accounts?: Record<string, Record<string, number>>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function buildKillswitchThresholdSeed(
|
|
17
|
+
config: KillswitchDialogConfig,
|
|
18
|
+
accountIds: string[],
|
|
19
|
+
) {
|
|
20
|
+
const readT = (t: Record<string, number> | undefined) => {
|
|
21
|
+
const fh = t?.five_hour ?? t?.['5h'] ?? 5
|
|
22
|
+
const sd = t?.seven_day ?? t?.['1w'] ?? 10
|
|
23
|
+
const scoped = t?.scoped ?? 0
|
|
24
|
+
return { fh, sd, scoped }
|
|
25
|
+
}
|
|
26
|
+
const mainT = readT(config.main)
|
|
27
|
+
const seedParts = [`main:${mainT.fh},${mainT.sd},${mainT.scoped}`]
|
|
28
|
+
for (const id of accountIds) {
|
|
29
|
+
const t = readT(config.accounts?.[id] ?? config.main)
|
|
30
|
+
seedParts.push(`${id}:${t.fh},${t.sd},${t.scoped}`)
|
|
31
|
+
}
|
|
32
|
+
return seedParts.join(' ')
|
|
33
|
+
}
|
|
34
|
+
|
|
10
35
|
function showText(api: TuiPluginApi, text: string) {
|
|
11
36
|
api.ui.dialog.setSize('xlarge')
|
|
12
37
|
api.ui.dialog.replace(() => (
|
|
@@ -150,25 +175,10 @@ export function openCommandDialog(
|
|
|
150
175
|
}
|
|
151
176
|
|
|
152
177
|
if (payload.command === 'claude-killswitch') {
|
|
153
|
-
const config = (payload.knobs.config ?? {}) as
|
|
154
|
-
enabled?: boolean
|
|
155
|
-
main?: Record<string, number>
|
|
156
|
-
accounts?: Record<string, Record<string, number>>
|
|
157
|
-
}
|
|
178
|
+
const config = (payload.knobs.config ?? {}) as KillswitchDialogConfig
|
|
158
179
|
const accountIds = (payload.knobs.accountIds as string[]) ?? []
|
|
159
180
|
const enabled = config.enabled === true
|
|
160
|
-
const
|
|
161
|
-
const fh = t?.five_hour ?? t?.['5h'] ?? 5
|
|
162
|
-
const sd = t?.seven_day ?? t?.['1w'] ?? 10
|
|
163
|
-
return { fh, sd }
|
|
164
|
-
}
|
|
165
|
-
const mainT = readT(config.main)
|
|
166
|
-
const seedParts = [`main:${mainT.fh},${mainT.sd}`]
|
|
167
|
-
for (const id of accountIds) {
|
|
168
|
-
const t = readT(config.accounts?.[id] ?? config.main)
|
|
169
|
-
seedParts.push(`${id}:${t.fh},${t.sd}`)
|
|
170
|
-
}
|
|
171
|
-
const seed = seedParts.join(' ')
|
|
181
|
+
const seed = buildKillswitchThresholdSeed(config, accountIds)
|
|
172
182
|
|
|
173
183
|
const openEdit = () => {
|
|
174
184
|
const DialogPrompt = api.ui.DialogPrompt
|
|
@@ -177,7 +187,7 @@ export function openCommandDialog(
|
|
|
177
187
|
<DialogPrompt
|
|
178
188
|
title='Killswitch thresholds'
|
|
179
189
|
description={() => <text>{payload.text}</text>}
|
|
180
|
-
placeholder='main:5,10 work-alt:5,10'
|
|
190
|
+
placeholder='main:5,10,0 work-alt:5,10,0'
|
|
181
191
|
value={seed}
|
|
182
192
|
onConfirm={(value: string) => {
|
|
183
193
|
void apply('claude-killswitch', `set ${value.trim()}`).then((r) => {
|
|
@@ -206,7 +216,7 @@ export function openCommandDialog(
|
|
|
206
216
|
{
|
|
207
217
|
title: 'Edit thresholds…',
|
|
208
218
|
value: 'edit',
|
|
209
|
-
description: 'Set per-account 5h,1w cutoffs',
|
|
219
|
+
description: 'Set per-account 5h,1w,scoped cutoffs',
|
|
210
220
|
},
|
|
211
221
|
]}
|
|
212
222
|
onSelect={(option) => {
|
package/src/tui.tsx
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
computeQuotaPacing,
|
|
24
24
|
DEFAULT_SIDEBAR_STATE,
|
|
25
25
|
FIVE_HOUR_MS,
|
|
26
|
+
formatScopedQuotaLabel,
|
|
26
27
|
getCollapsedQuotaSummary,
|
|
27
28
|
getSidebarState,
|
|
28
29
|
type QuotaPacing,
|
|
@@ -348,6 +349,17 @@ function AccountBlock(props: {
|
|
|
348
349
|
window={props.quota?.seven_day}
|
|
349
350
|
pacing={pacingFor(props.quota?.seven_day, SEVEN_DAY_MS)}
|
|
350
351
|
/>
|
|
352
|
+
<For each={props.quota?.scoped ?? []}>
|
|
353
|
+
{(window) => (
|
|
354
|
+
<QuotaRow
|
|
355
|
+
theme={props.theme}
|
|
356
|
+
appearance={props.appearance}
|
|
357
|
+
label={formatScopedQuotaLabel(window.title)}
|
|
358
|
+
window={window}
|
|
359
|
+
pacing={pacingFor(window, SEVEN_DAY_MS)}
|
|
360
|
+
/>
|
|
361
|
+
)}
|
|
362
|
+
</For>
|
|
351
363
|
</Show>
|
|
352
364
|
</box>
|
|
353
365
|
)
|
|
@@ -548,9 +560,21 @@ function QuotaSidebar(props: {
|
|
|
548
560
|
const quota = activeAccount().quota
|
|
549
561
|
if (!quota) return false
|
|
550
562
|
const now = Date.now()
|
|
551
|
-
const windows: Array<
|
|
563
|
+
const windows: Array<
|
|
564
|
+
[
|
|
565
|
+
(
|
|
566
|
+
| { usedPercent: number; remainingPercent: number; resetsAt?: string }
|
|
567
|
+
| undefined
|
|
568
|
+
),
|
|
569
|
+
number,
|
|
570
|
+
]
|
|
571
|
+
> = [
|
|
552
572
|
[quota.five_hour, FIVE_HOUR_MS],
|
|
553
573
|
[quota.seven_day, SEVEN_DAY_MS],
|
|
574
|
+
...(quota.scoped ?? []).map((window): [typeof window, number] => [
|
|
575
|
+
window,
|
|
576
|
+
SEVEN_DAY_MS,
|
|
577
|
+
]),
|
|
554
578
|
]
|
|
555
579
|
return windows.some(
|
|
556
580
|
([w, ms]) =>
|
|
@@ -562,6 +586,7 @@ function QuotaSidebar(props: {
|
|
|
562
586
|
const values = [
|
|
563
587
|
summary.fiveHourUsedPercent,
|
|
564
588
|
summary.sevenDayUsedPercent,
|
|
589
|
+
...summary.scopedUsedPercents,
|
|
565
590
|
].filter((value): value is number => value != null)
|
|
566
591
|
// Pacing deficit is an advisory projection, not actual quota exhaustion,
|
|
567
592
|
// so it can only BUMP the usage tone up to warn at most — never soften a
|