@pure01fx/dsh-openai-codex-auth 0.8.0 → 0.9.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/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.9.0
6
+
7
+ ### Codex 0.153 compatibility
8
+
9
+ - Tracks Codex main snapshot `ddf04ad` and uses the stable `0.153.4` model-catalog client version after auditing the intervening Responses, WebSocket, OAuth, Catalog, and quota protocol changes.
10
+ - Preserves the complete bounded `response.completed.response.usage` object alongside the exact high-precision `usage_metadata.amount` value across HTTP/SSE, WebSocket, and same-origin status responses.
11
+ - Supports GPT-6-Astra and its Fast alias through the complete Responses Lite contract: stable developer instruction/tool prefix items, namespaced functions, all-turn reasoning context, model-default verbosity, disabled parallel tool calls, the HTTP Lite header, and the WebSocket request-metadata route marker. Standard Responses requests remain unchanged.
12
+ - Recognizes `normal_model_slug` on additional `wham/usage` limits and honors the backend's `allowed` decision when `limit_reached` is absent, while intentionally remaining a passive client without the Luna Reserve opt-in header.
13
+ - Shows an isolated quota snapshot, including remaining reset credits, for every managed account, refreshing once when Codex settings opens or on explicit request; concurrent usage lookups are time-bounded outside the main credential lock, rotating refresh operations are journaled, bounded independently of caller cancellation, single-flighted per account across service processes, recoverable after persistence contention, and never ambiguously retried, stale non-current credentials are renewed without changing the selected account, and one account's failure does not hide the others.
14
+
5
15
  ## 0.8.0
6
16
 
7
17
  ### Multi-account authentication
package/client.js CHANGED
@@ -181,6 +181,7 @@ window.__ModuleLoader__.load({
181
181
  .codexButton:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover);border-color:var(--dsw-alias-border-l3)}.codexButton:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.codexButton:disabled{color:var(--dsw-alias-label-dimmed);cursor:not-allowed}
182
182
  .codexButton.primary{border-color:transparent;background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-foreground)}.codexButton.primary:hover:not(:disabled){border-color:transparent;background:var(--dsw-alias-button-primary-hover)}.codexButton.danger{color:var(--dsw-alias-state-error-primary)}
183
183
  .codexGrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;margin-top:14px}
184
+ .codexAccounts{margin-top:14px;margin-bottom:20px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:14px}.codexAccountList{display:flex;flex-direction:column;gap:8px}.codexAccountOption{display:flex;align-items:center;justify-content:space-between;gap:18px;min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:12px 14px;background:var(--dsw-alias-bg-layer-2)}.codexAccountDetails{flex:1;min-width:0}.codexAccountTitle{display:flex;align-items:center;flex-wrap:wrap;gap:6px 10px;min-width:0}.codexAccountTitle strong{font-size:13px;font-weight:500;overflow-wrap:anywhere}.codexAccountTitle .codexBadge{padding:1px 8px;line-height:18px}.codexAccountMeta{display:flex;flex-wrap:wrap;gap:2px 14px;margin-top:4px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.codexAccountActions{flex:none;flex-wrap:nowrap;margin-top:0}.codexAccountActions .codexButton{white-space:nowrap}.codexAccountHeaderActions{display:flex;align-items:center;gap:10px}.codexAccountRefresh{min-height:28px;padding:3px 9px;font-size:12px}.codexAccountQuota{display:flex;flex-wrap:wrap;gap:5px 14px;margin-top:10px;border-top:1px solid var(--dsw-alias-border-l2);padding-top:9px;color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}.codexAccountQuotaItem{white-space:nowrap}.codexAccountQuotaItem strong{color:var(--dsw-alias-label-primary);font-weight:500;font-variant-numeric:tabular-nums}.codexAccountQuotaStatus{color:var(--dsw-alias-label-tertiary)}.codexAccountQuotaStatus.error{color:var(--dsw-alias-state-error-primary)}
184
185
  .codexUsage{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;padding:12px 14px;background:var(--dsw-alias-bg-layer-2)}
185
186
  .codexUsageHead{display:flex;align-items:baseline;justify-content:space-between;gap:12px}.codexUsageName{font-size:13px;font-weight:500}.codexUsageValue{font-size:12px;color:var(--dsw-alias-label-tertiary)}
186
187
  .codexBar{height:6px;margin:10px 0 8px;overflow:hidden;border-radius:999px;background:var(--dsw-alias-bg-layer-1)}.codexBarFill{height:100%;border-radius:inherit;background:var(--dsw-alias-state-success-primary);transition:width .25s ease}.codexBarFill.high{background:var(--dsw-alias-state-warn-label)}
@@ -203,7 +204,7 @@ window.__ModuleLoader__.load({
203
204
  .codexQuotaTrack{fill:none;stroke:var(--dsw-alias-border-l3);stroke-width:2px}.codexQuotaAvailable{fill:none;stroke:var(--dsw-alias-state-success-primary);stroke-width:2px;stroke-linecap:round;transition:stroke .25s ease,stroke-dasharray .25s ease,stroke-dashoffset .25s ease}.codexQuotaAvailable.high{stroke:var(--dsw-alias-state-warn-label)}.codexQuotaAvailable.critical{stroke:var(--dsw-alias-state-error-primary)}.codexQuotaLoading{animation:codexQuotaPulse .8s ease-in-out infinite alternate}
204
205
  .codexQuotaPanel{z-index:100;box-sizing:border-box;width:272px;border:1px solid var(--dsw-alias-border-inverted);border-radius:12px;padding:12px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv3);color:var(--dsw-alias-label-secondary);cursor:default;font-size:12px;line-height:20px;position:absolute;right:0;bottom:calc(100% + 8px)}.codexQuotaPanelHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px}.codexQuotaPanelHead strong{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:500}.codexQuotaPanelHead span{color:var(--dsw-alias-label-tertiary)}
205
206
  .codexQuotaWindow{padding:7px 0}.codexQuotaWindow+.codexQuotaWindow{border-top:1px solid var(--dsw-alias-border-l2)}.codexQuotaWindowHead{display:flex;align-items:center;justify-content:space-between;gap:10px}.codexQuotaWindowHead strong{font-weight:500;color:var(--dsw-alias-label-secondary)}.codexQuotaWindowHead span{font-variant-numeric:tabular-nums;color:var(--dsw-alias-label-primary)}.codexQuotaBar{height:4px;margin:6px 0;border-radius:999px;overflow:hidden;background:var(--dsw-alias-interactive-bg-hover)}.codexQuotaBarFill{height:100%;border-radius:inherit;background:var(--dsw-alias-state-success-primary)}.codexQuotaBarFill.high{background:var(--dsw-alias-state-warn-label)}.codexQuotaBarFill.critical{background:var(--dsw-alias-state-error-primary)}.codexQuotaReset{color:var(--dsw-alias-label-tertiary)}.codexQuotaMessage{margin:4px 0;color:var(--dsw-alias-label-tertiary)}.codexQuotaMessage.error{color:var(--dsw-alias-state-error-primary)}
206
- @keyframes codexPulse{to{background-position:-200% 0}}@keyframes codexQuotaPulse{to{opacity:.35}}@media(prefers-reduced-motion:reduce){.codexSkeleton,.codexQuotaLoading{animation:none}}@media(max-width:620px){.codexHero{padding:14px;flex-direction:column}.codexBody{padding:14px}.codexGrid,.codexModelVisibilityList{grid-template-columns:1fr}.codexCode{font-size:20px}}
207
+ @keyframes codexPulse{to{background-position:-200% 0}}@keyframes codexQuotaPulse{to{opacity:.35}}@media(prefers-reduced-motion:reduce){.codexSkeleton,.codexQuotaLoading{animation:none}}@media(max-width:620px){.codexHero{padding:14px;flex-direction:column}.codexBody{padding:14px}.codexGrid,.codexModelVisibilityList{grid-template-columns:1fr}.codexAccountOption{align-items:stretch;flex-direction:column;gap:10px}.codexAccountActions{align-self:flex-start}.codexCode{font-size:20px}}
207
208
  `
208
209
  if (typeof document !== 'undefined' && document.querySelector('style[data-plugin="' + PLUGIN_ID + '"]') === null) {
209
210
  const style = document.createElement('style')
@@ -341,6 +342,26 @@ window.__ModuleLoader__.load({
341
342
  )
342
343
  }
343
344
 
345
+ function AccountQuotaSummary(props) {
346
+ const entry = props.entry
347
+ if (props.loading && !entry) return h('div', { className: 'codexAccountQuota' }, h('span', { className: 'codexAccountQuotaStatus' }, '正在读取额度…'))
348
+ if (!entry) return h('div', { className: 'codexAccountQuota' }, h('span', { className: 'codexAccountQuotaStatus' }, '尚未读取额度'))
349
+ if (entry.error) return h('div', { className: 'codexAccountQuota' }, h('span', { className: 'codexAccountQuotaStatus error', role: 'status' }, '额度读取失败:' + entry.error))
350
+ const usage = entry.usage
351
+ if (!usage) return h('div', { className: 'codexAccountQuota' }, h('span', { className: 'codexAccountQuotaStatus' }, '暂无额度数据'))
352
+ const rows = []
353
+ if (usage.planType) rows.push(h('span', { className: 'codexAccountQuotaItem', key: 'plan' }, String(usage.planType).toUpperCase()))
354
+ if (displayQuotaWindow(usage.primary)) rows.push(h('span', { className: 'codexAccountQuotaItem', key: 'primary' }, quotaWindowName(usage.primary, false) + ' ', h('strong', null, '剩余 ' + Math.max(0, Math.round(100 - usage.primary.usedPercent)) + '%')))
355
+ if (displayQuotaWindow(usage.secondary)) rows.push(h('span', { className: 'codexAccountQuotaItem', key: 'secondary' }, quotaWindowName(usage.secondary, true) + ' ', h('strong', null, '剩余 ' + Math.max(0, Math.round(100 - usage.secondary.usedPercent)) + '%')))
356
+ if (Number.isFinite(usage.resetCredits)) rows.push(h('span', { className: 'codexAccountQuotaItem', key: 'resetCredits' }, '额度重置 ', h('strong', null, '剩余 ' + Math.max(0, Math.floor(usage.resetCredits)) + ' 次')))
357
+ if (usage.credits) {
358
+ const credits = usage.credits.unlimited ? '无限' : usage.credits.hasCredits ? (usage.credits.balance || '可用') : '不可用'
359
+ rows.push(h('span', { className: 'codexAccountQuotaItem', key: 'credits' }, 'Credits ', h('strong', null, credits)))
360
+ }
361
+ if (usage.fetchedAt) rows.push(h('span', { className: 'codexAccountQuotaItem', key: 'updated' }, '更新 ' + new Date(usage.fetchedAt).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })))
362
+ return h('div', { className: 'codexAccountQuota' }, rows.length > 0 ? rows : h('span', { className: 'codexAccountQuotaStatus' }, '暂无额度数据'))
363
+ }
364
+
344
365
  function quotaTone(used) {
345
366
  return used >= 95 ? ' critical' : used >= 80 ? ' high' : ''
346
367
  }
@@ -484,7 +505,13 @@ window.__ModuleLoader__.load({
484
505
  const [manualInput, setManualInput] = useState('')
485
506
  const [now, setNow] = useState(Date.now())
486
507
  const [modelVisibility, setModelVisibility] = useState(readModelVisibility)
508
+ const [accountUsages, setAccountUsages] = useState({})
509
+ const [accountUsageBusy, setAccountUsageBusy] = useState(false)
510
+ const [accountUsageError, setAccountUsageError] = useState('')
511
+ const [accountStatusSyncError, setAccountStatusSyncError] = useState('')
487
512
  const probeGeneration = useRef(0)
513
+ const accountUsageGeneration = useRef(0)
514
+ const accountUsageScope = useRef('')
488
515
 
489
516
  useEffect(() => {
490
517
  const reload = () => { setModelVisibility(readModelVisibility()) }
@@ -566,6 +593,52 @@ window.__ModuleLoader__.load({
566
593
  return value
567
594
  }, [status])
568
595
 
596
+ const refreshAccountUsages = useCallback(async () => {
597
+ const generation = ++accountUsageGeneration.current
598
+ setAccountUsageBusy(true)
599
+ setAccountUsageError('')
600
+ setAccountStatusSyncError('')
601
+ try {
602
+ const value = await post('/accounts/usage')
603
+ const next = {}
604
+ for (const row of Array.isArray(value.accounts) ? value.accounts : []) {
605
+ if (row && typeof row.accountId === 'string') next[row.accountId] = row
606
+ }
607
+ if (generation === accountUsageGeneration.current) {
608
+ setAccountUsages(next)
609
+ try {
610
+ await requestStatus(false)
611
+ } catch (statusError) {
612
+ if (generation === accountUsageGeneration.current) {
613
+ setAccountStatusSyncError('额度已刷新,但账号状态同步失败:' + messageOf(statusError))
614
+ }
615
+ }
616
+ }
617
+ } catch (usageError) {
618
+ if (generation === accountUsageGeneration.current) setAccountUsageError(messageOf(usageError))
619
+ } finally {
620
+ if (generation === accountUsageGeneration.current) setAccountUsageBusy(false)
621
+ }
622
+ }, [post])
623
+
624
+ const accountUsageIds = status && Array.isArray(status.accounts)
625
+ ? status.accounts.map(account => account.accountId).filter(Boolean).sort().join('\n')
626
+ : ''
627
+ useEffect(() => {
628
+ if (!status || !status.csrf || !accountUsageIds) {
629
+ if (accountUsageScope.current) {
630
+ accountUsageScope.current = ''
631
+ setAccountUsages({})
632
+ setAccountUsageError('')
633
+ setAccountStatusSyncError('')
634
+ }
635
+ return
636
+ }
637
+ if (accountUsageScope.current === accountUsageIds) return
638
+ accountUsageScope.current = accountUsageIds
639
+ void refreshAccountUsages()
640
+ }, [accountUsageIds, refreshAccountUsages, status && status.csrf])
641
+
569
642
  const startDevice = async () => {
570
643
  setBusy('device')
571
644
  setCopied(false)
@@ -787,23 +860,33 @@ window.__ModuleLoader__.load({
787
860
  )
788
861
  : null,
789
862
  !loading && accounts.length > 0
790
- ? h('div', { className: 'codexModelVisibility' },
863
+ ? h('div', { className: 'codexAccounts' },
791
864
  h('div', { className: 'codexModelVisibilityHead' },
792
865
  h('strong', null, '已添加账号'),
793
- h('span', { className: 'codexMeta' }, accounts.length + ' 个'),
866
+ h('div', { className: 'codexAccountHeaderActions' },
867
+ h('span', { className: 'codexMeta' }, accounts.length + ' 个'),
868
+ h('button', { type: 'button', className: 'codexButton codexAccountRefresh', disabled: accountUsageBusy, onClick: () => { void refreshAccountUsages() } }, accountUsageBusy ? '刷新中…' : '刷新额度'),
869
+ ),
794
870
  ),
795
- h('p', { className: 'codexModelVisibilityHint' }, '当前账号用于新的 Codex 请求;你可以切换或单独移除任意账号。'),
796
- h('div', { className: 'codexModelVisibilityList' }, accounts.map((account) => {
871
+ h('p', { className: 'codexModelVisibilityHint' }, '当前账号用于新的 Codex 请求;每个账号的额度仅在打开本页或点击刷新时读取。'),
872
+ accountUsageError ? h('p', { className: 'codexAccountQuotaStatus error', role: 'status' }, '额度刷新失败:' + accountUsageError) : null,
873
+ accountStatusSyncError ? h('p', { className: 'codexAccountQuotaStatus error', role: 'status' }, accountStatusSyncError) : null,
874
+ h('div', { className: 'codexAccountList' }, accounts.map((account) => {
797
875
  const isCurrent = account.current === true || account.accountId === currentAccountId
798
876
  const accountBusy = busy === 'current:' + account.accountId || busy === 'remove:' + account.accountId
799
- return h('div', { className: 'codexModelVisibilityOption', key: account.accountId },
800
- h('span', { title: account.accountId },
801
- h('strong', null, account.email || shortAccount(account.accountId)),
802
- account.email ? h('span', null, ' · ' + shortAccount(account.accountId)) : null,
803
- h('span', null, isCurrent ? ' · 当前账号' : ''),
804
- account.expiresAt ? h('span', null, ' · 到期 ' + new Date(account.expiresAt).toLocaleString()) : null,
877
+ return h('div', { className: 'codexAccountOption', key: account.accountId },
878
+ h('div', { className: 'codexAccountDetails', title: account.accountId },
879
+ h('div', { className: 'codexAccountTitle' },
880
+ h('strong', null, account.email || shortAccount(account.accountId)),
881
+ isCurrent ? h('span', { className: 'codexBadge connected' }, '当前账号') : null,
882
+ ),
883
+ h('div', { className: 'codexAccountMeta' },
884
+ account.email ? h('span', null, shortAccount(account.accountId)) : null,
885
+ account.expiresAt ? h('span', null, '到期 ' + new Date(account.expiresAt).toLocaleString()) : null,
886
+ ),
887
+ h(AccountQuotaSummary, { entry: accountUsages[account.accountId], loading: accountUsageBusy }),
805
888
  ),
806
- h('div', { className: 'codexActions' },
889
+ h('div', { className: 'codexActions codexAccountActions' },
807
890
  !isCurrent ? h('button', { type: 'button', className: 'codexButton', disabled: Boolean(busy), onClick: () => { void setCurrentAccount(account.accountId) } }, accountBusy && busy.startsWith('current:') ? '切换中…' : '设为当前') : null,
808
891
  h('button', { type: 'button', className: 'codexButton danger', disabled: Boolean(busy), onClick: () => { void removeAccount(account.accountId) } }, accountBusy && busy.startsWith('remove:') ? '移除中…' : '移除'),
809
892
  ),
package/lib/catalog.d.ts CHANGED
@@ -31,6 +31,11 @@ export interface NativeCodexModel {
31
31
  additionalSpeedTiers: readonly string[];
32
32
  serviceTiers: readonly NativeCodexServiceTier[];
33
33
  defaultServiceTier?: string;
34
+ /** Requires the model-specific Responses Lite wire contract, not Standard Responses. */
35
+ useResponsesLite?: boolean;
36
+ /** Catalog-provided defaults needed to construct the model-specific request. */
37
+ defaultVerbosity?: string;
38
+ instructionsTemplate?: string;
34
39
  contextWindow?: number;
35
40
  inputModalities: readonly string[];
36
41
  }
package/lib/catalog.js CHANGED
@@ -128,6 +128,7 @@ function parseModel(value) {
128
128
  const additionalSpeedTiers = strictStringList(row?.additional_speed_tiers);
129
129
  const serviceTiers = parseServiceTiers(row?.service_tiers);
130
130
  const inputModalities = strictStringList(row?.input_modalities, ['text', 'image']);
131
+ const useResponsesLite = row?.use_responses_lite ?? false;
131
132
  if (slug === undefined
132
133
  || displayName === undefined
133
134
  || reasoning === undefined
@@ -138,6 +139,7 @@ function parseModel(value) {
138
139
  || priority < -2_147_483_648 || priority > 2_147_483_647
139
140
  || additionalSpeedTiers === undefined
140
141
  || serviceTiers === undefined
142
+ || typeof useResponsesLite !== 'boolean'
141
143
  || inputModalities === undefined
142
144
  || !inputModalities.every(value => ['text', 'image', 'audio'].includes(value))) {
143
145
  throw invalidCatalog('native Codex catalog contained an invalid model entry');
@@ -160,6 +162,18 @@ function parseModel(value) {
160
162
  && nonEmptyString(row.multi_agent_reasoning_effort) === undefined) {
161
163
  throw invalidCatalog('native Codex catalog contained an invalid multi-agent reasoning effort');
162
164
  }
165
+ if (row.default_verbosity !== undefined && row.default_verbosity !== null
166
+ && nonEmptyString(row.default_verbosity) === undefined) {
167
+ throw invalidCatalog('native Codex catalog contained an invalid default verbosity');
168
+ }
169
+ const modelMessages = row.model_messages === undefined || row.model_messages === null
170
+ ? undefined : record(row.model_messages);
171
+ if ((row.model_messages !== undefined && row.model_messages !== null && modelMessages === undefined)
172
+ || (modelMessages?.instructions_template !== undefined
173
+ && modelMessages.instructions_template !== null
174
+ && nonEmptyString(modelMessages.instructions_template) === undefined)) {
175
+ throw invalidCatalog('native Codex catalog contained invalid model instructions');
176
+ }
163
177
  for (const key of ['context_window', 'max_context_window']) {
164
178
  if (row[key] !== undefined && row[key] !== null && positiveNumber(row[key]) === undefined) {
165
179
  throw invalidCatalog('native Codex catalog contained an invalid context window');
@@ -169,6 +183,8 @@ function parseModel(value) {
169
183
  const defaultReasoningLevel = nonEmptyString(row.default_reasoning_level);
170
184
  const multiAgentReasoningEffort = nonEmptyString(row.multi_agent_reasoning_effort);
171
185
  const defaultServiceTier = nonEmptyString(row.default_service_tier);
186
+ const defaultVerbosity = nonEmptyString(row.default_verbosity);
187
+ const instructionsTemplate = nonEmptyString(modelMessages?.instructions_template);
172
188
  const contextWindow = positiveNumber(row.context_window) ?? positiveNumber(row.max_context_window);
173
189
  return {
174
190
  slug,
@@ -183,6 +199,9 @@ function parseModel(value) {
183
199
  additionalSpeedTiers,
184
200
  serviceTiers,
185
201
  ...defaultServiceTier === undefined ? {} : { defaultServiceTier },
202
+ useResponsesLite,
203
+ ...defaultVerbosity === undefined ? {} : { defaultVerbosity },
204
+ ...instructionsTemplate === undefined ? {} : { instructionsTemplate },
186
205
  ...contextWindow === undefined ? {} : { contextWindow },
187
206
  inputModalities,
188
207
  };
package/lib/index.d.ts CHANGED
@@ -132,6 +132,8 @@ export declare class OpenAICodexAuth extends Service {
132
132
  private usageError;
133
133
  private usageRefresh;
134
134
  private usageGeneration;
135
+ private accountUsageRequestGeneration;
136
+ private readonly accountUsageCredentialRefreshes;
135
137
  private directUsageSequence;
136
138
  private directUsageAccountId;
137
139
  private usageHasDirectDefault;
@@ -156,9 +158,9 @@ export declare class OpenAICodexAuth extends Service {
156
158
  private commitDocument;
157
159
  private upsertCurrentCredential;
158
160
  private commitCredential;
159
- private resolveManagedCredentialLocked;
160
161
  /** Return the current managed bearer token, refreshing and migrating it when needed. */
161
162
  bearerToken(signal?: AbortSignal): Promise<string | undefined>;
163
+ private managedCredential;
162
164
  private externalNativeCredential;
163
165
  private resolveNativeCredential;
164
166
  private nativeRecoveryError;
@@ -173,8 +175,22 @@ export declare class OpenAICodexAuth extends Service {
173
175
  private cancelLogin;
174
176
  private resetCurrentAccountState;
175
177
  private setCurrentAccount;
178
+ private logoutAttempt;
176
179
  private logout;
177
180
  private status;
181
+ private accountRefreshJournalFilename;
182
+ private readAccountRefreshJournal;
183
+ private writeAccountRefreshJournal;
184
+ private clearAccountRefreshJournal;
185
+ private removeDeadFileLock;
186
+ private withAccountRefreshLock;
187
+ private withAccountRefreshLocks;
188
+ private reconcileAccountRefreshJournal;
189
+ private refreshManagedAccount;
190
+ private persistAccountUsageCredential;
191
+ private refreshAccountUsageCredential;
192
+ private accountUsageCredential;
193
+ private accountUsages;
178
194
  private fetchUsage;
179
195
  private write;
180
196
  private sendJson;
@@ -182,6 +198,7 @@ export declare class OpenAICodexAuth extends Service {
182
198
  private trustedManagementRequest;
183
199
  private requireCsrf;
184
200
  private handleStatus;
201
+ private handleAccountUsage;
185
202
  private handleDeviceStart;
186
203
  private handleBrowserStart;
187
204
  private handleBrowserPrepare;