@cortexkit/opencode-openai-auth 0.3.3 → 0.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 (57) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +1 -1
  3. package/dist/codex-http.d.ts +3 -0
  4. package/dist/config.d.ts +3 -0
  5. package/dist/core/accounts.d.ts +9 -3
  6. package/dist/core/oauth.d.ts +1 -1
  7. package/dist/core/quota-manager.d.ts +2 -2
  8. package/dist/{index-k5zwf3j1.js → index-1anzb8jh.js} +1 -1
  9. package/dist/index-1r02s323.js +6 -0
  10. package/dist/index-2ng03cby.js +2 -0
  11. package/dist/{index-e7m7qbne.js → index-6y6ss1kc.js} +1 -1
  12. package/dist/{index-1xmasv0x.js → index-b6kp9ydc.js} +1 -1
  13. package/dist/index-cz1bkmjz.js +2 -0
  14. package/dist/index-dzg88nw2.js +89 -0
  15. package/dist/index-y67qn95a.js +2 -0
  16. package/dist/index.d.ts +8 -1
  17. package/dist/index.js +65 -65
  18. package/dist/model-costs.d.ts +29 -0
  19. package/dist/prompt-context.d.ts +1 -1
  20. package/dist/quota-normalize-8yzxqy78.js +1 -0
  21. package/dist/quota-normalize.d.ts +13 -4
  22. package/dist/rpc/port-file.js +1 -1
  23. package/dist/rpc/rpc-client.js +1 -1
  24. package/dist/rpc/rpc-dir.js +1 -1
  25. package/dist/sidebar-state.d.ts +47 -2
  26. package/dist/sidebar-state.js +1 -1
  27. package/dist/token-util-h46jb3eg.js +1 -0
  28. package/dist/token-yzcb1p3e.js +1 -0
  29. package/dist/tui/command-dialogs.d.ts +8 -1
  30. package/dist/tui-preferences.js +1 -1
  31. package/dist/tui.d.ts +18 -1
  32. package/dist/version.d.ts +1 -1
  33. package/dist/ws-pool.d.ts +1 -0
  34. package/package.json +11 -8
  35. package/src/core/refresh-file-lock.ts +293 -0
  36. package/src/sidebar-state.ts +392 -13
  37. package/src/tui/command-dialogs.tsx +43 -25
  38. package/src/tui/entry.mjs +37 -0
  39. package/src/tui-compiled/logger.ts +161 -0
  40. package/src/tui-compiled/rpc/port-file.ts +70 -0
  41. package/src/tui-compiled/rpc/protocol.ts +31 -0
  42. package/src/tui-compiled/rpc/rpc-client.ts +78 -0
  43. package/src/tui-compiled/rpc/rpc-dir.ts +22 -0
  44. package/src/tui-compiled/sidebar-state.ts +695 -0
  45. package/src/tui-compiled/tui/command-dialogs.tsx +645 -0
  46. package/src/tui-compiled/tui-preferences.ts +328 -0
  47. package/src/tui-compiled/tui.tsx +1098 -0
  48. package/src/tui-compiled/util/open-url.ts +30 -0
  49. package/src/tui.tsx +158 -77
  50. package/dist/index-5s67238f.js +0 -2
  51. package/dist/index-d9hq0tmc.js +0 -2
  52. package/dist/index-mrg2fms9.js +0 -2
  53. package/dist/index-phrx93zy.js +0 -92
  54. package/dist/index-qdh7pt5a.js +0 -3
  55. package/dist/quota-normalize-dfdpwwm3.js +0 -1
  56. package/dist/token-01dcf92a.js +0 -1
  57. package/dist/token-util-rkqd82q9.js +0 -1
@@ -0,0 +1,30 @@
1
+ import { execFileSync as defaultExecFileSync } from 'node:child_process'
2
+
3
+ type BrowserExec = (
4
+ file: string,
5
+ args: string[],
6
+ options: { stdio: 'ignore'; timeout: number },
7
+ ) => unknown
8
+
9
+ export function openUrl(
10
+ url: string,
11
+ platform: NodeJS.Platform = process.platform,
12
+ execFileSync: BrowserExec = defaultExecFileSync,
13
+ ) {
14
+ try {
15
+ if (platform === 'win32') {
16
+ execFileSync('cmd', ['/c', 'start', '', url], {
17
+ stdio: 'ignore',
18
+ timeout: 3000,
19
+ })
20
+ return
21
+ }
22
+
23
+ execFileSync(platform === 'darwin' ? 'open' : 'xdg-open', [url], {
24
+ stdio: 'ignore',
25
+ timeout: 3000,
26
+ })
27
+ } catch {
28
+ // Browser launch is best effort; the printed URL remains the fallback.
29
+ }
30
+ }
package/src/tui.tsx CHANGED
@@ -23,12 +23,13 @@ import {
23
23
  type AccountQuota,
24
24
  computeQuotaPacing,
25
25
  DEFAULT_SIDEBAR_STATE,
26
- FIVE_HOUR_MS,
27
26
  getCollapsedQuotaSummary,
27
+ getPresentQuotaWindows,
28
28
  getSidebarState,
29
29
  type QuotaPacing,
30
+ type QuotaWindow,
30
31
  resolveActiveAccount,
31
- SEVEN_DAY_MS,
32
+ resolveSessionSidebarRouting,
32
33
  type SidebarState,
33
34
  } from './sidebar-state.js'
34
35
  import { openCommandDialog } from './tui/command-dialogs.js'
@@ -50,21 +51,24 @@ const log = createLogger('rpc-tui')
50
51
 
51
52
  const ID = 'cortexkit.openai-auth'
52
53
 
53
- // Plugin version for the header (mirrors the Magic Context / AFT convention).
54
- // Read at runtime from package.json relative to this module — NOT a TS JSON
55
- // import, which would break the declaration build (package.json is outside
56
- // rootDir). tui.tsx ships as source (package.json exports["./tui"] →
57
- // "./src/tui.tsx") and is never compiled into a deeper dist tree, so `..` from
58
- // src/ is always the package root. Empty string on any failure → header shows
59
- // the badge with no version.
54
+ // Read package metadata from either the raw src/ entry or its generated
55
+ // src/tui-compiled/ counterpart. Avoid a JSON import because package.json sits
56
+ // outside the declaration build's rootDir.
60
57
  const PLUGIN_VERSION: string = (() => {
61
- try {
62
- const here = dirname(fileURLToPath(import.meta.url))
63
- const raw = readFileSync(join(here, '..', 'package.json'), 'utf8')
64
- return (JSON.parse(raw) as { version?: string }).version ?? ''
65
- } catch {
66
- return ''
58
+ const here = dirname(fileURLToPath(import.meta.url))
59
+ for (const packageFile of [
60
+ join(here, '..', 'package.json'),
61
+ join(here, '..', '..', 'package.json'),
62
+ ]) {
63
+ try {
64
+ const raw = readFileSync(packageFile, 'utf8')
65
+ const version = (JSON.parse(raw) as { version?: string }).version
66
+ if (version) return version
67
+ } catch {
68
+ // Try the path for the other TUI entry layout.
69
+ }
67
70
  }
71
+ return ''
68
72
  })()
69
73
 
70
74
  // biome-ignore lint/suspicious/noExplicitAny: opentui border prop not typed in plugin tui surface
@@ -225,6 +229,54 @@ function CollapsedRow(props: {
225
229
  )
226
230
  }
227
231
 
232
+ export interface QuotaDisplayRow {
233
+ key: 'primary' | 'secondary'
234
+ label: string
235
+ window: QuotaWindow
236
+ pacing: QuotaPacing | null
237
+ }
238
+
239
+ // Maps present quota windows onto display rows and computes pacing against each
240
+ // dynamic duration or the historical 5h/7d duration for legacy snapshots.
241
+ export function buildQuotaRowsForDisplay(
242
+ quota: AccountQuota | null,
243
+ now: number,
244
+ pacingEnabled: boolean,
245
+ ): QuotaDisplayRow[] {
246
+ return getPresentQuotaWindows(quota).map((row) => ({
247
+ key: row.key,
248
+ label: row.label,
249
+ window: row.window,
250
+ pacing:
251
+ pacingEnabled && row.windowMs !== null
252
+ ? computeQuotaPacing(row.window, row.windowMs, now)
253
+ : null,
254
+ }))
255
+ }
256
+
257
+ export function isQuotaLoaded(quota: AccountQuota | null): boolean {
258
+ return quota !== null
259
+ }
260
+
261
+ export function getQuotaMetadataRows(
262
+ state: SidebarState,
263
+ ): Array<{ label: string; value: string }> {
264
+ const rows: Array<{ label: string; value: string }> = []
265
+ if (state.planType) rows.push({ label: 'Plan', value: state.planType })
266
+ if (state.credits !== undefined) {
267
+ rows.push({ label: 'Credits', value: String(state.credits) })
268
+ }
269
+ return rows
270
+ }
271
+
272
+ export function getAccountMetadataRows(
273
+ resetCredits: number | undefined,
274
+ ): Array<{ label: string; value: string }> {
275
+ return resetCredits === undefined
276
+ ? []
277
+ : [{ label: 'resets', value: String(resetCredits) }]
278
+ }
279
+
228
280
  // Quota window row: muted label left, tone-colored bar + percentage right,
229
281
  // with an optional muted reset suffix. When pacing data is present, the bar
230
282
  // gains a pace segment and an off-pace window adds a muted subline with the
@@ -308,21 +360,15 @@ function AccountBlock(props: {
308
360
  killed: boolean
309
361
  active: boolean
310
362
  pacingEnabled: boolean
363
+ resetCredits?: number
311
364
  marginTop?: number
312
365
  }) {
313
366
  const statusWord = () =>
314
367
  props.killed ? 'blocked' : props.active ? 'active' : 'idle'
315
368
  const statusTone = (): Tone =>
316
369
  props.killed ? 'err' : props.active ? 'ok' : 'muted'
317
- const pacingFor = (
318
- window:
319
- | { usedPercent: number; remainingPercent: number; resetsAt?: string }
320
- | undefined,
321
- windowMs: number,
322
- ) =>
323
- props.pacingEnabled && window
324
- ? computeQuotaPacing(window, windowMs, Date.now())
325
- : null
370
+ const rows = () =>
371
+ buildQuotaRowsForDisplay(props.quota, Date.now(), props.pacingEnabled)
326
372
  return (
327
373
  <box width='100%' flexDirection='column' marginTop={props.marginTop ?? 0}>
328
374
  <box width='100%' flexDirection='row' justifyContent='space-between'>
@@ -334,24 +380,36 @@ function AccountBlock(props: {
334
380
  </text>
335
381
  </box>
336
382
  <Show
337
- when={props.quota}
383
+ when={isQuotaLoaded(props.quota)}
338
384
  fallback={<text fg={props.theme.textMuted}>{'checking\u2026'}</text>}
339
385
  >
340
- <QuotaRow
341
- theme={props.theme}
342
- appearance={props.appearance}
343
- label='5h'
344
- window={props.quota?.primary}
345
- pacing={pacingFor(props.quota?.primary, FIVE_HOUR_MS)}
346
- />
347
- <QuotaRow
348
- theme={props.theme}
349
- appearance={props.appearance}
350
- label='7d'
351
- window={props.quota?.secondary}
352
- pacing={pacingFor(props.quota?.secondary, SEVEN_DAY_MS)}
353
- />
386
+ <Show
387
+ when={rows().length > 0}
388
+ fallback={<text fg={props.theme.textMuted}>{'\u2014'}</text>}
389
+ >
390
+ <For each={rows()}>
391
+ {(row) => (
392
+ <QuotaRow
393
+ theme={props.theme}
394
+ appearance={props.appearance}
395
+ label={row.label}
396
+ window={row.window}
397
+ pacing={row.pacing}
398
+ />
399
+ )}
400
+ </For>
401
+ </Show>
354
402
  </Show>
403
+ <For each={getAccountMetadataRows(props.resetCredits)}>
404
+ {(row) => (
405
+ <StatRow
406
+ theme={props.theme}
407
+ label={row.label}
408
+ value={row.value}
409
+ tone='text'
410
+ />
411
+ )}
412
+ </For>
355
413
  </box>
356
414
  )
357
415
  }
@@ -363,6 +421,7 @@ function AccountBlock(props: {
363
421
  function QuotaDialogContent(props: {
364
422
  api: TuiPluginApi
365
423
  controller: SidebarController
424
+ sessionId: string | undefined
366
425
  }) {
367
426
  const prefs = props.controller.prefs
368
427
  const [state, setState] = createSignal<SidebarState>(DEFAULT_SIDEBAR_STATE)
@@ -382,6 +441,7 @@ function QuotaDialogContent(props: {
382
441
  const theme = () => props.api.theme.current
383
442
  const enabledFallbacks = () =>
384
443
  (state().fallbacks ?? []).filter((f) => f.enabled)
444
+ const activeId = () => resolveQuotaDialogActiveId(state(), props.sessionId)
385
445
  return (
386
446
  <box flexDirection='column' padding={2} width='100%' alignItems='center'>
387
447
  <box flexDirection='column' width={58}>
@@ -396,8 +456,9 @@ function QuotaDialogContent(props: {
396
456
  name='main'
397
457
  quota={state().main?.quota ?? null}
398
458
  killed={state().main?.killed ?? false}
399
- active={state().activeId === 'main'}
459
+ active={activeId() === 'main'}
400
460
  pacingEnabled={prefs().sections.pacing}
461
+ resetCredits={state().main?.resetCredits}
401
462
  />
402
463
  <Show when={prefs().sections.fallbackAccounts}>
403
464
  <For each={enabledFallbacks()}>
@@ -408,8 +469,9 @@ function QuotaDialogContent(props: {
408
469
  name={fb.label ?? fb.id}
409
470
  quota={fb.quota}
410
471
  killed={fb.killed}
411
- active={state().activeId === fb.id}
472
+ active={activeId() === fb.id}
412
473
  pacingEnabled={prefs().sections.pacing}
474
+ resetCredits={fb.resetCredits}
413
475
  marginTop={1}
414
476
  />
415
477
  )}
@@ -426,6 +488,16 @@ export async function readStateFromFile(): Promise<SidebarState> {
426
488
  return getSidebarState()
427
489
  }
428
490
 
491
+ export function resolveQuotaDialogActiveId(
492
+ state: SidebarState,
493
+ sessionId: string | undefined,
494
+ now = Date.now(),
495
+ ): string | undefined {
496
+ return sessionId
497
+ ? resolveSessionSidebarRouting(state, sessionId, now).activeId
498
+ : state.activeId
499
+ }
500
+
429
501
  interface SidebarController {
430
502
  prefs: () => OpenaiAuthTuiPrefs
431
503
  collapsed: () => boolean
@@ -493,6 +565,7 @@ function createSidebarController(
493
565
  function QuotaSidebar(props: {
494
566
  api: TuiPluginApi
495
567
  controller: SidebarController
568
+ sessionId: string
496
569
  }) {
497
570
  const prefs = props.controller.prefs
498
571
  const collapsed = props.controller.collapsed
@@ -544,22 +617,23 @@ function QuotaSidebar(props: {
544
617
  const name = prefs().header.label
545
618
  return !hasData() ? name : collapsed() ? `\u25b6 ${name}` : `\u25bc ${name}`
546
619
  }
547
- const activeAccount = () => resolveActiveAccount(state())
620
+ const sessionRouting = () =>
621
+ resolveSessionSidebarRouting(state(), props.sessionId)
622
+ const sessionState = (): SidebarState => ({
623
+ ...state(),
624
+ activeId: sessionRouting().activeId,
625
+ route: sessionRouting().route,
626
+ })
627
+ const activeAccount = () => resolveActiveAccount(sessionState())
548
628
  const activeQuotaSummary = () =>
549
629
  getCollapsedQuotaSummary(activeAccount().quota)
550
630
  const activePacingDeficit = () => {
551
631
  if (!prefs().sections.pacing) return false
552
- const quota = activeAccount().quota
553
- if (!quota) return false
554
- const now = Date.now()
555
- const windows: Array<[typeof quota.primary, number]> = [
556
- [quota.primary, FIVE_HOUR_MS],
557
- [quota.secondary, SEVEN_DAY_MS],
558
- ]
559
- return windows.some(
560
- ([w, ms]) =>
561
- w != null && computeQuotaPacing(w, ms, now)?.state === 'deficit',
562
- )
632
+ return buildQuotaRowsForDisplay(
633
+ activeAccount().quota,
634
+ Date.now(),
635
+ true,
636
+ ).some((row) => row.pacing?.state === 'deficit')
563
637
  }
564
638
  const activeQuotaTone = (): Tone => {
565
639
  const summary = activeQuotaSummary()
@@ -637,7 +711,7 @@ function QuotaSidebar(props: {
637
711
  </Show>
638
712
  </box>
639
713
 
640
- {/* Collapsed: active account 5h + 7d quota + dot (red ⊘ when killed) */}
714
+ {/* Collapsed: active account's present quota windows + dot (red ⊘ when killed) */}
641
715
  <Show when={collapsed() && hasData()}>
642
716
  <CollapsedRow theme={theme()} label={activeAccount().name}>
643
717
  <Show
@@ -681,8 +755,9 @@ function QuotaSidebar(props: {
681
755
  name='main'
682
756
  quota={state().main?.quota ?? null}
683
757
  killed={state().main?.killed ?? false}
684
- active={state().activeId === 'main'}
758
+ active={sessionRouting().activeId === 'main'}
685
759
  pacingEnabled={prefs().sections.pacing}
760
+ resetCredits={state().main?.resetCredits}
686
761
  />
687
762
  <Show when={prefs().sections.fallbackAccounts}>
688
763
  <For each={enabledFallbacks()}>
@@ -693,8 +768,9 @@ function QuotaSidebar(props: {
693
768
  name={fb.label ?? fb.id}
694
769
  quota={fb.quota}
695
770
  killed={fb.killed}
696
- active={state().activeId === fb.id}
771
+ active={sessionRouting().activeId === fb.id}
697
772
  pacingEnabled={prefs().sections.pacing}
773
+ resetCredits={fb.resetCredits}
698
774
  marginTop={1}
699
775
  />
700
776
  )}
@@ -709,30 +785,22 @@ function QuotaSidebar(props: {
709
785
  <StatRow
710
786
  theme={theme()}
711
787
  label='Route'
712
- value={state().route}
788
+ value={sessionRouting().route}
713
789
  tone='accent'
714
790
  />
715
791
  </Show>
716
792
 
717
- {/* Plan + Credits */}
718
- <Show when={state().planType || state().credits != null}>
719
- <Show when={state().planType}>
793
+ {/* Plan and credits — whichever are present */}
794
+ <For each={getQuotaMetadataRows(state())}>
795
+ {(row) => (
720
796
  <StatRow
721
797
  theme={theme()}
722
- label='Plan'
723
- value={state().planType ?? '\u2014'}
798
+ label={row.label}
799
+ value={row.value}
724
800
  tone='text'
725
801
  />
726
- </Show>
727
- <Show when={state().credits != null}>
728
- <StatRow
729
- theme={theme()}
730
- label='Credits'
731
- value={String(state().credits)}
732
- tone='text'
733
- />
734
- </Show>
735
- </Show>
802
+ )}
803
+ </For>
736
804
 
737
805
  {/* Health — only when something is wrong */}
738
806
  <Show when={degraded() && prefs().sections.health}>
@@ -773,8 +841,14 @@ const tui: TuiPlugin = async (api) => {
773
841
  api.slots.register({
774
842
  order: computeEffectiveOrder(root, PLUGIN_KEY, DEFAULT_SLOT_ORDER),
775
843
  slots: {
776
- sidebar_content(_ctx: unknown, _props: { session_id: string }) {
777
- return <QuotaSidebar api={api} controller={controller} />
844
+ sidebar_content(_ctx: unknown, props: { session_id: string }) {
845
+ return (
846
+ <QuotaSidebar
847
+ api={api}
848
+ controller={controller}
849
+ sessionId={props.session_id}
850
+ />
851
+ )
778
852
  },
779
853
  },
780
854
  })
@@ -812,12 +886,19 @@ const tui: TuiPlugin = async (api) => {
812
886
  if (message.payload.command === 'openai-quota') {
813
887
  api.ui.dialog.setSize('xlarge')
814
888
  api.ui.dialog.replace(() => (
815
- <QuotaDialogContent api={api} controller={controller} />
889
+ <QuotaDialogContent
890
+ api={api}
891
+ controller={controller}
892
+ sessionId={sessionId}
893
+ />
816
894
  ))
817
895
  continue
818
896
  }
819
- openCommandDialog(api, message.payload, (command, args) =>
820
- rpcClient.apply({ command, arguments: args }),
897
+ openCommandDialog(
898
+ api,
899
+ message.payload,
900
+ (command, args) => rpcClient.apply({ command, arguments: args }),
901
+ sessionId,
821
902
  )
822
903
  }
823
904
  })
@@ -1,2 +0,0 @@
1
- import{ia as Y,ka as K}from"./index-e7m7qbne.js";var V=Y((rz,O)=>{var{defineProperty:J,getOwnPropertyDescriptor:r,getOwnPropertyNames:t}=Object,e=Object.prototype.hasOwnProperty,o=(z,B)=>{for(var F in B)J(z,F,{get:B[F],enumerable:!0})},zz=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of t(B))if(!e.call(z,G)&&G!==F)J(z,G,{get:()=>B[G],enumerable:!(H=r(B,G))||H.enumerable})}return z},Bz=(z)=>zz(J({},"__esModule",{value:!0}),z),M={};o(M,{VercelOidcTokenError:()=>j});O.exports=Bz(M);class j extends Error{constructor(z,B){super(z);this.name="VercelOidcTokenError",this.cause=B}toString(){if(this.cause)return`${this.name}: ${this.message}: ${this.cause}`;return`${this.name}: ${this.message}`}}});var C=Y((tz,x)=>{var{create:Fz,defineProperty:v,getOwnPropertyDescriptor:Gz,getOwnPropertyNames:Hz,getPrototypeOf:Kz}=Object,Qz=Object.prototype.hasOwnProperty,Wz=(z,B)=>{for(var F in B)v(z,F,{get:B[F],enumerable:!0})},S=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of Hz(B))if(!Qz.call(z,G)&&G!==F)v(z,G,{get:()=>B[G],enumerable:!(H=Gz(B,G))||H.enumerable})}return z},N=(z,B,F)=>(F=z!=null?Fz(Kz(z)):{},S(B||!z||!z.__esModule?v(F,"default",{value:z,enumerable:!0}):F,z)),Xz=(z)=>S(v({},"__esModule",{value:!0}),z),E={};Wz(E,{findRootDir:()=>$z,getUserDataDir:()=>qz});x.exports=Xz(E);var Z=N(K("path")),Yz=N(K("fs")),A=N(K("os")),Zz=V();function $z(){try{let z=process.cwd();while(z!==Z.default.dirname(z)){let B=Z.default.join(z,".vercel");if(Yz.default.existsSync(B))return z;z=Z.default.dirname(z)}}catch(z){throw new Zz.VercelOidcTokenError("Token refresh only supported in node server environments")}return null}function qz(){if(process.env.XDG_DATA_HOME)return process.env.XDG_DATA_HOME;switch(A.default.platform()){case"darwin":return Z.default.join(A.default.homedir(),"Library/Application Support");case"linux":return Z.default.join(A.default.homedir(),".local/share");case"win32":if(process.env.LOCALAPPDATA)return process.env.LOCALAPPDATA;return null;default:return null}}});var c=Y((ez,g)=>{var{create:vz,defineProperty:b,getOwnPropertyDescriptor:bz,getOwnPropertyNames:Uz,getPrototypeOf:Lz}=Object,Jz=Object.prototype.hasOwnProperty,Vz=(z,B)=>{for(var F in B)b(z,F,{get:B[F],enumerable:!0})},y=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of Uz(B))if(!Jz.call(z,G)&&G!==F)b(z,G,{get:()=>B[G],enumerable:!(H=bz(B,G))||H.enumerable})}return z},u=(z,B,F)=>(F=z!=null?vz(Lz(z)):{},y(B||!z||!z.__esModule?b(F,"default",{value:z,enumerable:!0}):F,z)),Az=(z)=>y(b({},"__esModule",{value:!0}),z),P={};Vz(P,{isValidAccessToken:()=>wz,readAuthConfig:()=>Rz,writeAuthConfig:()=>Iz});g.exports=Az(P);var $=u(K("fs")),l=u(K("path")),Nz=k();function h(){let z=(0,Nz.getVercelDataDir)();if(!z)throw Error(`Unable to find Vercel CLI data directory. Your platform: ${process.platform}. Supported: darwin, linux, win32.`);return l.join(z,"auth.json")}function Rz(){try{let z=h();if(!$.existsSync(z))return null;let B=$.readFileSync(z,"utf8");if(!B)return null;return JSON.parse(B)}catch(z){return null}}function Iz(z){let B=h(),F=l.dirname(B);if(!$.existsSync(F))$.mkdirSync(F,{mode:504,recursive:!0});$.writeFileSync(B,JSON.stringify(z,null,2),{mode:384})}function wz(z){if(!z.token)return!1;if(typeof z.expiresAt!=="number")return!0;let B=Math.floor(Date.now()/1000);return z.expiresAt>=B}});var p=Y((oz,d)=>{var{defineProperty:w,getOwnPropertyDescriptor:Dz,getOwnPropertyNames:Tz}=Object,Mz=Object.prototype.hasOwnProperty,jz=(z,B)=>{for(var F in B)w(z,F,{get:B[F],enumerable:!0})},Oz=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of Tz(B))if(!Mz.call(z,G)&&G!==F)w(z,G,{get:()=>B[G],enumerable:!(H=Dz(B,G))||H.enumerable})}return z},Sz=(z)=>Oz(w({},"__esModule",{value:!0}),z),i={};jz(i,{processTokenResponse:()=>uz,refreshTokenRequest:()=>yz});d.exports=Sz(i);var R=K("os"),Ez="https://vercel.com",xz="cl_HYyOPBNtFMfHhaUn9L4QPfTZz6TP47bp",f=`@vercel/oidc node-${process.version} ${(0,R.platform)()} (${(0,R.arch)()}) ${(0,R.hostname)()}`,I=null;async function Cz(){if(I)return I;let z=`${Ez}/.well-known/openid-configuration`,B=await fetch(z,{headers:{"user-agent":f}});if(!B.ok)throw Error("Failed to discover OAuth endpoints");let F=await B.json();if(!F||typeof F.token_endpoint!=="string")throw Error("Invalid OAuth discovery response");let H=F.token_endpoint;return I=H,H}async function yz(z){let B=await Cz();return await fetch(B,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded","user-agent":f},body:new URLSearchParams({client_id:xz,grant_type:"refresh_token",...z})})}async function uz(z){let B=await z.json();if(!z.ok){let F=typeof B==="object"&&B&&"error"in B?String(B.error):"Token refresh failed";return[Error(F)]}if(typeof B!=="object"||B===null)return[Error("Invalid token response")];if(typeof B.access_token!=="string")return[Error("Missing access_token in response")];if(B.token_type!=="Bearer")return[Error("Invalid token_type in response")];if(typeof B.expires_in!=="number")return[Error("Missing expires_in in response")];return[null,B]}});var k=Y((zB,n)=>{var{create:Pz,defineProperty:U,getOwnPropertyDescriptor:lz,getOwnPropertyNames:hz,getPrototypeOf:gz}=Object,cz=Object.prototype.hasOwnProperty,kz=(z,B)=>{for(var F in B)U(z,F,{get:B[F],enumerable:!0})},a=(z,B,F,H)=>{if(B&&typeof B==="object"||typeof B==="function"){for(let G of hz(B))if(!cz.call(z,G)&&G!==F)U(z,G,{get:()=>B[G],enumerable:!(H=lz(B,G))||H.enumerable})}return z},_=(z,B,F)=>(F=z!=null?Pz(gz(z)):{},a(B||!z||!z.__esModule?U(F,"default",{value:z,enumerable:!0}):F,z)),iz=(z)=>a(U({},"__esModule",{value:!0}),z),m={};kz(m,{assertVercelOidcTokenResponse:()=>D,findProjectInfo:()=>sz,getTokenPayload:()=>mz,getVercelCliToken:()=>dz,getVercelDataDir:()=>fz,getVercelOidcToken:()=>pz,isExpired:()=>nz,loadToken:()=>_z,saveToken:()=>az});n.exports=iz(m);var q=_(K("path")),Q=_(K("fs")),X=V(),L=C(),W=c(),s=p();function fz(){let B=(0,L.getUserDataDir)();if(!B)return null;return q.join(B,"com.vercel.cli")}async function dz(){let z=(0,W.readAuthConfig)();if(!z)return null;if((0,W.isValidAccessToken)(z))return z.token||null;if(!z.refreshToken)return(0,W.writeAuthConfig)({}),null;try{let B=await(0,s.refreshTokenRequest)({refresh_token:z.refreshToken}),[F,H]=await(0,s.processTokenResponse)(B);if(F||!H)return(0,W.writeAuthConfig)({}),null;let G={token:H.access_token,expiresAt:Math.floor(Date.now()/1000)+H.expires_in};if(H.refresh_token)G.refreshToken=H.refresh_token;return(0,W.writeAuthConfig)(G),G.token??null}catch(B){return(0,W.writeAuthConfig)({}),null}}async function pz(z,B,F){let H=`https://api.vercel.com/v1/projects/${B}/token?source=vercel-oidc-refresh${F?`&teamId=${F}`:""}`,G=await fetch(H,{method:"POST",headers:{Authorization:`Bearer ${z}`}});if(!G.ok)throw new X.VercelOidcTokenError(`Failed to refresh OIDC token: ${G.statusText}`);let T=await G.json();return D(T),T}function D(z){if(!z||typeof z!=="object")throw TypeError("Vercel OIDC token is malformed. Expected an object. Please run `vc env pull` and try again");if(!("token"in z)||typeof z.token!=="string")throw TypeError("Vercel OIDC token is malformed. Expected a string-valued token property. Please run `vc env pull` and try again")}function sz(){let z=(0,L.findRootDir)();if(!z)throw new X.VercelOidcTokenError("Unable to find project root directory. Have you linked your project with `vc link?`");let B=q.join(z,".vercel","project.json");if(!Q.existsSync(B))throw new X.VercelOidcTokenError("project.json not found, have you linked your project with `vc link?`");let F=JSON.parse(Q.readFileSync(B,"utf8"));if(typeof F.projectId!=="string"&&typeof F.orgId!=="string")throw TypeError("Expected a string-valued projectId property. Try running `vc link` to re-link your project.");return{projectId:F.projectId,teamId:F.orgId}}function az(z,B){let F=(0,L.getUserDataDir)();if(!F)throw new X.VercelOidcTokenError("Unable to find user data directory. Please reach out to Vercel support.");let H=q.join(F,"com.vercel.token",`${B}.json`),G=JSON.stringify(z);Q.mkdirSync(q.dirname(H),{mode:504,recursive:!0}),Q.writeFileSync(H,G),Q.chmodSync(H,432);return}function _z(z){let B=(0,L.getUserDataDir)();if(!B)throw new X.VercelOidcTokenError("Unable to find user data directory. Please reach out to Vercel support.");let F=q.join(B,"com.vercel.token",`${z}.json`);if(!Q.existsSync(F))return null;let H=JSON.parse(Q.readFileSync(F,"utf8"));return D(H),H}function mz(z){let B=z.split(".");if(B.length!==3)throw new X.VercelOidcTokenError("Invalid token. Please run `vc env pull` and try again");let F=B[1].replace(/-/g,"+").replace(/_/g,"/"),H=F.padEnd(F.length+(4-F.length%4)%4,"=");return JSON.parse(Buffer.from(H,"base64").toString("utf8"))}function nz(z){return z.exp*1000<Date.now()}});
2
- export{V as a,k as b};
@@ -1,2 +0,0 @@
1
- function A(b){if(b==null||b==="")return;let g=typeof b==="number"?b:Number(b);if(Number.isFinite(g)){let q=g<100000000000?g*1000:g,B=new Date(q);return Number.isNaN(B.getTime())?void 0:B.toISOString()}let z=new Date(b);return Number.isNaN(z.getTime())?void 0:z.toISOString()}function C(b,g){let z=b.get(g);if(z===null||z.trim()==="")return;let q=Number(z);if(!Number.isFinite(q)||q<0||q>100)return;return{usedPercent:q,remainingPercent:100-q,resetsAt:A(b.get(`${g.slice(0,-13)}-reset-at`)??void 0),checkedAt:Date.now()}}function G(b){let g={},z=C(b,"x-codex-primary-used-percent");if(z)g.primary=z;let q=C(b,"x-codex-secondary-used-percent");if(q)g.secondary=q;return g}function D(b){if(!b)return;if(!Number.isFinite(b.used_percent)||b.used_percent<0||b.used_percent>100)return;return{usedPercent:b.used_percent,remainingPercent:100-b.used_percent,resetsAt:A(b.reset_at),checkedAt:Date.now()}}function J(b){let g={},z=D(b.rate_limits?.primary);if(z)g.primary=z;let q=D(b.rate_limits?.secondary);if(q)g.secondary=q;return g}function E(b){if(!b)return;if(!Number.isFinite(b.used_percent)||b.used_percent<0||b.used_percent>100)return;return{usedPercent:b.used_percent,remainingPercent:100-b.used_percent,resetsAt:A(b.reset_at),checkedAt:Date.now()}}function K(b){let g={},z=E(b.rate_limit?.primary_window);if(z)g.primary=z;let q=E(b.rate_limit?.secondary_window);if(q)g.secondary=q;return g}
2
- export{A as c,G as d,J as e,K as f};
@@ -1,2 +0,0 @@
1
- import{ca as v}from"./index-qdh7pt5a.js";import{randomUUID as O}from"node:crypto";import{mkdir as N,readFile as C,rename as g,rm as h,writeFile as k}from"node:fs/promises";import{tmpdir as L}from"node:os";import{dirname as D,join as R}from"node:path";var F=v("sidebar"),M="OPENCODE_OPENAI_AUTH_SIDEBAR_STATE_FILE",I=R(L(),"opencode-openai-auth"),f=R(I,"sidebar-state.json");function W(){return process.env[M]||f}var B={main:{quota:null,killed:!1},fallbacks:[],activeId:void 0,route:"main",lastUpdated:0};function b(K){if(K===null||typeof K!=="object"||Array.isArray(K))return B;let x=K,J=x.main,Q;if(J!==null&&typeof J==="object"&&!Array.isArray(J)){let H=J;Q={quota:"quota"in H?H.quota:null,killed:typeof H.killed==="boolean"?H.killed:!1,...typeof H.quotaBackedOff==="boolean"?{quotaBackedOff:H.quotaBackedOff}:{},...typeof H.quotaBackoffUntil==="number"?{quotaBackoffUntil:H.quotaBackoffUntil}:{},...typeof H.refreshBackedOff==="boolean"?{refreshBackedOff:H.refreshBackedOff}:{},...typeof H.refreshBackoffUntil==="number"?{refreshBackoffUntil:H.refreshBackoffUntil}:{}}}else Q={quota:null,killed:!1};let Y=x.fallbacks,X=Array.isArray(Y)?Y.filter((H)=>H!==null&&typeof H==="object"&&!Array.isArray(H)&&typeof H.id==="string").map((H)=>({id:H.id,label:typeof H.label==="string"?H.label:void 0,quota:"quota"in H?H.quota:null,killed:typeof H.killed==="boolean"?H.killed:!1,enabled:typeof H.enabled==="boolean"?H.enabled:!0})):[],Z=typeof x.activeId==="string"?x.activeId:void 0,V=typeof x.route==="string"?x.route:B.route,$=typeof x.lastUpdated==="number"?x.lastUpdated:0,j=typeof x.planType==="string"?x.planType:void 0,z=typeof x.credits==="number"?x.credits:void 0;return{main:Q,fallbacks:X,activeId:Z,route:V,lastUpdated:$,...j!==void 0?{planType:j}:{},...z!==void 0?{credits:z}:{}}}async function A(){try{let K=await C(W(),"utf8");return b(JSON.parse(K))}catch{return B}}var G=Promise.resolve();function m(K,x=W()){return G=G.then(()=>U(K,x)).catch(()=>{}),G}async function U(K,x){let J=`${x}.${O()}.tmp`;try{await N(D(x),{recursive:!0}),await k(J,JSON.stringify(K),"utf8"),await g(J,x)}catch(Q){await h(J,{force:!0}).catch(()=>{}),F.warn("sidebar write failed",{pid:process.pid,error:Q instanceof Error?Q.message:String(Q)})}}function w(){return G}function c(K){let x=K.activeId;if(x&&x!=="main"){let J=K.fallbacks.find((Q)=>Q.enabled&&Q.id===x);if(J)return{id:J.id,name:J.label??J.id,quota:J.quota,killed:J.killed}}return{id:"main",name:"main",quota:K.main.quota,killed:K.main.killed}}function l(K){let x=K?.primary?.usedPercent??null,J=K?.secondary?.usedPercent??null;if(x==null&&J==null)return{primaryUsedPercent:x,secondaryUsedPercent:J,text:null};return{primaryUsedPercent:x,secondaryUsedPercent:J,text:`5h: ${x==null?"—":`${Math.round(x)}%`} 7d: ${J==null?"—":`${Math.round(J)}%`}`}}var o=18000000,d=604800000,_=300000,y=0.01,S=1;function s(K,x,J){if(!K.resetsAt)return null;let Q=new Date(K.resetsAt).getTime();if(!Number.isFinite(Q))return null;let Y=Q-x,X=J-Y;if(X<_)return null;if(X<x*y)return null;if(X>=x)return null;let Z=K.usedPercent,V=Math.min(Math.max(X/x*100,0),100),$=Z-V,j=Math.abs($)<S?"on-pace":$>0?"deficit":"reserve",z=null;if(Z>0){let H=X*100/Z,q=Y+H;if(q<Q)z=new Date(q).toISOString()}return{pacePercent:V,deltaPercent:$,state:j,runsOutAt:z}}
2
- export{W as R,B as S,b as T,A as U,m as V,w as W,c as X,l as Y,o as Z,d as _,s as $};