@cortexkit/opencode-openai-auth 0.7.2 → 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.
Files changed (118) hide show
  1. package/README.md +9 -5
  2. package/dist/index-301y4qa1.js +2 -0
  3. package/dist/index-338z7171.js +211 -0
  4. package/dist/index-5y4vzdf8.js +2 -0
  5. package/dist/{index-zxqb5ydj.js → index-9ehhb051.js} +1 -1
  6. package/dist/{index-zg1x8sty.js → index-jwn4r3sw.js} +1 -1
  7. package/dist/{index-9jpc8yct.js → index-sdt2d2ra.js} +1 -1
  8. package/dist/index-w42s0g6m.js +2 -0
  9. package/dist/index.d.ts +213 -36
  10. package/dist/index.js +59 -154
  11. package/dist/internal-Y7QNVDJT.d.ts +908 -0
  12. package/dist/quota-normalize-3qffywcm.js +1 -0
  13. package/dist/rpc/port-file.d.ts +11 -9
  14. package/dist/rpc/port-file.js +1 -1
  15. package/dist/rpc/protocol.d.ts +2 -21
  16. package/dist/rpc/rpc-client.d.ts +7 -4
  17. package/dist/rpc/rpc-client.js +1 -1
  18. package/dist/rpc/rpc-dir.d.ts +7 -5
  19. package/dist/rpc/rpc-dir.js +1 -1
  20. package/dist/sidebar-state-B98sERYt.d.ts +219 -0
  21. package/dist/sidebar-state.d.ts +2 -171
  22. package/dist/sidebar-state.js +1 -1
  23. package/dist/{token-bvp0y166.js → token-9823y0pc.js} +1 -1
  24. package/dist/token-util-ypgz7rge.js +1 -0
  25. package/dist/tui-preferences.d.ts +27 -26
  26. package/dist/tui-preferences.js +1 -1
  27. package/dist/tui.d.ts +42 -19
  28. package/package.json +8 -14
  29. package/src/tui/entry.mjs +2 -2
  30. package/src/tui-compiled/{core/account-paths.ts → raw/core-account-paths.ts} +29 -18
  31. package/src/tui-compiled/raw/core-custody-state.ts +243 -0
  32. package/src/tui-compiled/raw/logger.ts +53 -0
  33. package/src/tui-compiled/{rpc/port-file.ts → raw/rpc-port-file.ts} +1 -1
  34. package/src/tui-compiled/raw/rpc-protocol.ts +12 -0
  35. package/src/{rpc/rpc-client.ts → tui-compiled/raw/rpc-rpc-client.ts} +2 -2
  36. package/src/{sidebar-state.ts → tui-compiled/raw/sidebar-state.ts} +142 -13
  37. package/src/{tui/command-dialogs.tsx → tui-compiled/raw/tui-command-dialogs.tsx} +94 -44
  38. package/src/{tui.tsx → tui-compiled/raw/tui.tsx} +149 -28
  39. package/src/{core/account-paths.ts → tui-compiled/runtime/core-account-paths.ts} +29 -18
  40. package/src/tui-compiled/runtime/core-custody-state.ts +243 -0
  41. package/src/tui-compiled/runtime/logger.ts +53 -0
  42. package/src/{rpc/port-file.ts → tui-compiled/runtime/rpc-port-file.ts} +1 -1
  43. package/src/tui-compiled/runtime/rpc-protocol.ts +12 -0
  44. package/src/tui-compiled/{rpc/rpc-client.ts → runtime/rpc-rpc-client.ts} +2 -2
  45. package/src/tui-compiled/{sidebar-state.ts → runtime/sidebar-state.ts} +142 -13
  46. package/src/tui-compiled/{tui/command-dialogs.tsx → runtime/tui-command-dialogs.tsx} +73 -37
  47. package/src/tui-compiled/{tui.tsx → runtime/tui.tsx} +251 -153
  48. package/src/tui-compiled/shared/internal.ts +6 -0
  49. package/src/{logger.ts → tui-compiled/shared/logger.ts} +91 -23
  50. package/src/tui-compiled/shared/paths.ts +33 -0
  51. package/src/{core → tui-compiled/shared}/refresh-file-lock.ts +7 -4
  52. package/dist/cli.d.ts +0 -2
  53. package/dist/cli.js +0 -15
  54. package/dist/codex-http.d.ts +0 -3
  55. package/dist/commands.d.ts +0 -88
  56. package/dist/config.d.ts +0 -47
  57. package/dist/core/account-paths.d.ts +0 -25
  58. package/dist/core/accounts.d.ts +0 -330
  59. package/dist/core/atomic-write.d.ts +0 -1
  60. package/dist/core/background-quota-refresh.d.ts +0 -46
  61. package/dist/core/backoff.d.ts +0 -53
  62. package/dist/core/cachekeep.d.ts +0 -118
  63. package/dist/core/oauth.d.ts +0 -138
  64. package/dist/core/provider.d.ts +0 -70
  65. package/dist/core/quota-manager.d.ts +0 -192
  66. package/dist/core/refresh-all-quota.d.ts +0 -86
  67. package/dist/core/refresh-file-lock.d.ts +0 -12
  68. package/dist/core/reset-credits.d.ts +0 -116
  69. package/dist/core/sticky-routing.d.ts +0 -43
  70. package/dist/dump.d.ts +0 -20
  71. package/dist/hosted-web-search.d.ts +0 -5
  72. package/dist/index-87145jkw.js +0 -2
  73. package/dist/index-8f1200qx.js +0 -6
  74. package/dist/index-cfjed1st.js +0 -89
  75. package/dist/index-nrvjr97q.js +0 -3
  76. package/dist/index-qaggaze1.js +0 -2
  77. package/dist/index-sdcpzbnk.js +0 -2
  78. package/dist/logger.d.ts +0 -22
  79. package/dist/model-costs.d.ts +0 -29
  80. package/dist/prompt-context.d.ts +0 -19
  81. package/dist/quota-normalize-dvwtmy7f.js +0 -1
  82. package/dist/quota-normalize.d.ts +0 -43
  83. package/dist/raw-ws-bun.d.ts +0 -40
  84. package/dist/raw-ws-node.d.ts +0 -37
  85. package/dist/raw-ws-upgrade.d.ts +0 -2
  86. package/dist/raw-ws.d.ts +0 -3
  87. package/dist/response-stream-error.d.ts +0 -12
  88. package/dist/rpc/notifications.d.ts +0 -5
  89. package/dist/rpc/rpc-server.d.ts +0 -17
  90. package/dist/token-util-jcj7k7pa.js +0 -1
  91. package/dist/tui/command-dialogs.d.ts +0 -21
  92. package/dist/util/error.d.ts +0 -1
  93. package/dist/util/open-url.d.ts +0 -6
  94. package/dist/util/proxy-env.d.ts +0 -4
  95. package/dist/util/record.d.ts +0 -1
  96. package/dist/util/stable-json.d.ts +0 -1
  97. package/dist/util/uuid-v7.d.ts +0 -1
  98. package/dist/version.d.ts +0 -1
  99. package/dist/ws-pool.d.ts +0 -57
  100. package/dist/ws.d.ts +0 -71
  101. package/src/rpc/notifications.ts +0 -54
  102. package/src/rpc/protocol.ts +0 -33
  103. package/src/rpc/rpc-server.ts +0 -172
  104. package/src/tui-compiled/core/refresh-file-lock.ts +0 -381
  105. package/src/tui-compiled/logger.ts +0 -196
  106. package/src/tui-compiled/rpc/protocol.ts +0 -33
  107. package/src/util/error.ts +0 -9
  108. package/src/util/open-url.ts +0 -30
  109. package/src/util/proxy-env.ts +0 -42
  110. package/src/util/record.ts +0 -3
  111. package/src/util/stable-json.ts +0 -15
  112. package/src/util/uuid-v7.ts +0 -18
  113. /package/src/{rpc/rpc-dir.ts → tui-compiled/raw/rpc-rpc-dir.ts} +0 -0
  114. /package/src/tui-compiled/{tui-preferences.ts → raw/tui-preferences.ts} +0 -0
  115. /package/src/tui-compiled/{rpc/rpc-dir.ts → runtime/rpc-rpc-dir.ts} +0 -0
  116. /package/src/{tui-preferences.ts → tui-compiled/runtime/tui-preferences.ts} +0 -0
  117. /package/src/tui-compiled/{util → shared/util}/error.ts +0 -0
  118. /package/src/tui-compiled/{util → shared/util}/open-url.ts +0 -0
@@ -0,0 +1,6 @@
1
+ // Generated by scripts/build-tui.ts. Do not edit.
2
+ export * from './logger.ts'
3
+ export * from './paths.ts'
4
+ export * from './refresh-file-lock.ts'
5
+ export * from './util/error.ts'
6
+ export * from './util/open-url.ts'
@@ -5,10 +5,8 @@ import {
5
5
  renameSync,
6
6
  statSync,
7
7
  } from 'node:fs'
8
- import { tmpdir } from 'node:os'
9
- import { join } from 'node:path'
10
8
 
11
- type Level = 'error' | 'warn' | 'info' | 'debug' | 'trace'
9
+ export type Level = 'error' | 'warn' | 'info' | 'debug' | 'trace'
12
10
  const ORDER: Record<Level, number> = {
13
11
  error: 0,
14
12
  warn: 1,
@@ -16,23 +14,63 @@ const ORDER: Record<Level, number> = {
16
14
  debug: 3,
17
15
  trace: 4,
18
16
  }
19
- const isTestEnv = process.env.NODE_ENV === 'test'
20
17
  const MAX_BYTES = 5 * 1024 * 1024
21
18
 
22
- function logFile(): string {
23
- return (
24
- process.env.OPENCODE_OPENAI_AUTH_LOG_FILE ??
25
- join(tmpdir(), 'opencode-openai-auth.log')
26
- )
27
- }
19
+ /**
20
+ * Where lines are written, and the level floor, as the host supplied them.
21
+ *
22
+ * Both start unset. A host decides where its log lives — that decision reads
23
+ * host environment variables and host directories, neither of which belongs in
24
+ * shared code — and calls `initLogger` before it runs any command. Until then
25
+ * every `log.*` call is a silent no-op: throwing would turn the first command a
26
+ * host forgot to wire into a crash, and buffering would hold credential-bearing
27
+ * lines for an init that may never arrive.
28
+ */
29
+ let logFileSource: string | (() => string) | undefined
30
+ let initLevelSource: Level | (() => Level | undefined) | undefined
28
31
  let runtimeLevel: Level | undefined
32
+
33
+ export interface InitLoggerOptions {
34
+ /**
35
+ * Path of the file lines are appended to, or a function returning it.
36
+ *
37
+ * A function is what a host passes when its destination can move while the
38
+ * process runs — an operator or a test changing the variable that names the
39
+ * log file expects the next line to land in the new file, and a value
40
+ * captured once at init would keep writing to the old one.
41
+ */
42
+ file: string | (() => string)
43
+ /** Level floor applied when no `setLogLevel` call has overridden it. */
44
+ level?: Level | (() => Level | undefined)
45
+ }
46
+
47
+ /**
48
+ * Point the logger at a host's file and level. Idempotent: calling it again
49
+ * replaces both. A runtime level installed by `setLogLevel` is deliberately
50
+ * left alone, because it is the operator's explicit choice and outranks the
51
+ * floor a host computed at start-up.
52
+ */
53
+ export function initLogger(options: InitLoggerOptions): void {
54
+ logFileSource = options.file
55
+ initLevelSource = options.level
56
+ }
57
+
29
58
  export function setLogLevel(l: Level | undefined) {
30
59
  if (l === undefined || l in ORDER) runtimeLevel = l
31
60
  }
61
+
62
+ function logFilePath(): string | undefined {
63
+ if (logFileSource === undefined) return undefined
64
+ const resolved =
65
+ typeof logFileSource === 'function' ? logFileSource() : logFileSource
66
+ return resolved || undefined
67
+ }
68
+
32
69
  function configuredLevel(): Level {
33
70
  if (runtimeLevel) return runtimeLevel
34
- const env = process.env.OPENCODE_OPENAI_AUTH_LOG_LEVEL as Level | undefined
35
- if (env && env in ORDER) return env
71
+ const floor =
72
+ typeof initLevelSource === 'function' ? initLevelSource() : initLevelSource
73
+ if (floor && floor in ORDER) return floor
36
74
  return 'info'
37
75
  }
38
76
 
@@ -47,12 +85,19 @@ function isSecretKey(key: string): boolean {
47
85
  // needed for debugging — so it is intentionally NOT redacted by name. The genuine
48
86
  // ChatGPT id is kept out of logs at the source instead.
49
87
  if (k === 'chatgptaccountid') return true
88
+ // Operator identity carried on a served vault credential. These arrived with
89
+ // the client widening that added `accountId`/`email`/`orgName`/`projectId`;
90
+ // they are personal data with no diagnostic value, so they never reach a log
91
+ // file. The structural guard is not logging a served credential wholesale —
92
+ // this list only closes the fields that exist today.
93
+ if (k === 'email' || k === 'orgname' || k === 'organizationname') return true
50
94
  if (k.includes('apikey')) return true
51
95
  if (k.endsWith('secret') || k.endsWith('password')) return true
52
96
  if (k.endsWith('token') && !k.endsWith('tokens')) return true
53
97
  return false
54
98
  }
55
- const TOKEN_VALUE = /\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b/g
99
+ const TOKEN_VALUE =
100
+ /\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b|ckh_[A-Za-z0-9_-]{20,}/g
56
101
  export function redact(value: unknown): unknown {
57
102
  return redactInner(value, new WeakSet<object>())
58
103
  }
@@ -123,9 +168,8 @@ function chmodPrivate(path: string) {
123
168
  /* never throw */
124
169
  }
125
170
  }
126
- function rotateIfNeeded() {
171
+ function rotateIfNeeded(f: string) {
127
172
  try {
128
- const f = logFile()
129
173
  if (!(existsSync(f) && statSync(f).size > MAX_BYTES)) return
130
174
  for (let i = ROTATE_KEEP - 1; i >= 1; i--) {
131
175
  if (existsSync(`${f}.${i}`)) {
@@ -141,13 +185,19 @@ function rotateIfNeeded() {
141
185
  /* never throw */
142
186
  }
143
187
  }
144
- function flush() {
188
+
189
+ /**
190
+ * Write whatever is buffered. Safe to call synchronously from a process-exit
191
+ * handler, which is how each host drains the buffer on shutdown.
192
+ */
193
+ export function flushLogs() {
145
194
  if (!buffer.length) return
195
+ const file = logFilePath()
146
196
  const text = buffer.join('')
147
197
  buffer = []
198
+ if (!file) return
148
199
  try {
149
- rotateIfNeeded()
150
- const file = logFile()
200
+ rotateIfNeeded(file)
151
201
  if (existsSync(file)) chmodPrivate(file)
152
202
  appendFileSync(file, text, { encoding: 'utf8', mode: 0o600 })
153
203
  } catch {
@@ -158,10 +208,9 @@ function schedule() {
158
208
  if (!timer)
159
209
  timer = setTimeout(() => {
160
210
  timer = undefined
161
- flush()
211
+ flushLogs()
162
212
  }, 500)
163
213
  }
164
- if (!isTestEnv) process.on('exit', flush)
165
214
 
166
215
  function safeSerialize(data: unknown): string {
167
216
  try {
@@ -172,13 +221,16 @@ function safeSerialize(data: unknown): string {
172
221
  }
173
222
 
174
223
  function emit(channel: string, level: Level, message: string, data?: unknown) {
224
+ // No destination means no host has initialised the logger. Drop the line
225
+ // rather than buffering it: see the note on logFileSource above.
226
+ if (logFileSource === undefined) return
175
227
  if (ORDER[level] > ORDER[configuredLevel()]) return
176
228
  const line =
177
- `[${new Date().toISOString()}] ${level.toUpperCase()} [${channel}] ${message}` +
229
+ `[${new Date().toISOString()}] ${level.toUpperCase()} [${channel}] ${redactStrings(message)}` +
178
230
  (data === undefined ? '' : safeSerialize(data)) +
179
231
  '\n'
180
232
  buffer.push(line)
181
- if (buffer.length >= 50) flush()
233
+ if (buffer.length >= 50) flushLogs()
182
234
  else schedule()
183
235
  }
184
236
 
@@ -192,5 +244,21 @@ export function createLogger(channel: string) {
192
244
  }
193
245
  }
194
246
  export async function flushForTest() {
195
- flush()
247
+ flushLogs()
248
+ }
249
+
250
+ /**
251
+ * Return the logger to its uninitialised state. Only a test needs this: a
252
+ * single process runs every test file, so a file path left over from one test
253
+ * would keep a later "logger was never initialised" case writing lines.
254
+ */
255
+ export function resetLoggerForTest() {
256
+ buffer = []
257
+ if (timer) {
258
+ clearTimeout(timer)
259
+ timer = undefined
260
+ }
261
+ logFileSource = undefined
262
+ initLevelSource = undefined
263
+ runtimeLevel = undefined
196
264
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Pure path values shared by every host.
3
+ *
4
+ * Nothing here reads an environment variable or knows where a host keeps its
5
+ * configuration. A host resolves its own two file paths and hands them to the
6
+ * store as an `AccountPaths`; the only thing that must not drift between hosts
7
+ * is the file name itself, which is why the constants live here rather than in
8
+ * each host's own resolver.
9
+ */
10
+
11
+ import { basename, dirname, join } from 'node:path'
12
+
13
+ export const ACCOUNT_FILE_NAME = 'openai-auth.json'
14
+ export const ACCOUNT_STATE_FILE_NAME = 'openai-auth-state.json'
15
+
16
+ /**
17
+ * The config file and the runtime-state file a store operation reads and writes.
18
+ *
19
+ * Both are required. A store function never derives one from the other, because
20
+ * a host may point its state file somewhere the derivation would not reach and
21
+ * a silently derived path would lock one file while writing another.
22
+ */
23
+ export interface AccountPaths {
24
+ configPath: string
25
+ statePath: string
26
+ }
27
+
28
+ /** Derive the state-file path from the config path without reading env vars. */
29
+ export function deriveStatePath(configPath: string): string {
30
+ return basename(configPath) === ACCOUNT_FILE_NAME
31
+ ? join(dirname(configPath), ACCOUNT_STATE_FILE_NAME)
32
+ : `${configPath}.state.json`
33
+ }
@@ -1,7 +1,6 @@
1
1
  import { randomUUID } from 'node:crypto'
2
2
  import { mkdir, readFile, rename, rm, stat, writeFile } from 'node:fs/promises'
3
3
  import { dirname, join } from 'node:path'
4
- import { getAccountStoragePath } from './account-paths'
5
4
 
6
5
  const setRefreshLockRenewalTimeout = globalThis.setTimeout.bind(globalThis)
7
6
  const clearRefreshLockRenewalTimeout = globalThis.clearTimeout.bind(globalThis)
@@ -18,7 +17,12 @@ export function isLostMarkerRaceError(error: unknown): boolean {
18
17
  export async function acquireRefreshFileLock(options: {
19
18
  name: string
20
19
  ttlMs: number
21
- path?: string
20
+ /**
21
+ * File the lock is named after. Required: the lock and the write it guards
22
+ * must target the same file, and a default resolved in here could only ever
23
+ * be one host's path.
24
+ */
25
+ path: string
22
26
  now?: () => number
23
27
  renew?: boolean
24
28
  renewIntervalMs?: number
@@ -37,8 +41,7 @@ export async function acquireRefreshFileLock(options: {
37
41
  | 'release-owner-confirmed',
38
42
  ) => void | Promise<void>
39
43
  }): Promise<{ release: () => Promise<void> } | null> {
40
- const accountPath = options.path ?? getAccountStoragePath()
41
- const lockPath = `${accountPath}.${options.name}.lock`
44
+ const lockPath = `${options.path}.${options.name}.lock`
42
45
  const legacyOwnerPath = join(lockPath, 'owner.json')
43
46
  const ownerId = randomUUID()
44
47
  const now = options.now ?? Date.now
package/dist/cli.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export { openUrl as openBrowserForLogin } from './util/open-url';
package/dist/cli.js DELETED
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
- import{J as C,K as E,L as X,r as $,y as q,z as B}from"./index-cfjed1st.js";import{ua as Y}from"./index-8f1200qx.js";import"./index-nrvjr97q.js";import{Ka as Z}from"./index-zxqb5ydj.js";import{execFileSync as U}from"node:child_process";function V(z,K=process.platform,H=U){try{if(K==="win32"){H("cmd",["/c","start","",z],{stdio:"ignore",timeout:3000});return}H(K==="darwin"?"open":"xdg-open",[z],{stdio:"ignore",timeout:3000})}catch{}}function W(){console.log(`Usage:
3
- npx @cortexkit/opencode-openai-auth login [--label <name>] [--headless]
4
- npx @cortexkit/opencode-openai-auth list
5
- npx @cortexkit/opencode-openai-auth remove <id>
6
-
7
- Fallback accounts are stored in:
8
- ${Y()}`)}function P(z){let K=[],H={};for(let N=0;N<z.length;N++){let j=z[N];if(!j)continue;if(j.startsWith("--")){let J=j.slice(2),D=z[N+1];if(D&&!D.startsWith("--"))H[J]=D,N++;else H[J]=!0}else K.push(j)}return{positional:K,flags:H}}async function R(){let{positional:z,flags:K}=P(process.argv.slice(2)),[H,...N]=z;if(!H||H==="help")W(),process.exit(0);switch(H){case"login":{let j=typeof K.label==="string"?K.label:void 0,J=Boolean(K.headless);try{$(j)}catch(G){console.error(`
9
- Error: ${G instanceof Error?G.message:String(G)}`),process.exit(1)}let{url:D,instructions:M,completion:T}=await B({label:j,headless:J});if(console.log(`
10
- Open this URL in your browser and complete sign-in:
11
- `),console.log(`${D}
12
- `),M)console.log(`${M}
13
- `);V(D);let O=await T,Q=!1;if(await X((G)=>{if(O.accountId&&G.mainAccountId&&O.accountId===G.mainAccountId)return Q=!0,G;return q(G.accounts,O),G}),Q)console.error(`
14
- Error: that account is already your main (same ChatGPT account).`),console.error("A self-fallback would retry on the account that just returned 429."),process.exit(1);if(console.log(`
15
- ✓ Added account ${O.id}`),O.label)console.log(` Label: ${O.label}`);break}case"list":{let j=await E();if(!j||j.accounts.length===0)console.log("No fallback accounts configured.");else for(let J of j.accounts){let D=J.label,M=[` ${J.id}`];if(D)M.push(`(${D})`);M.push(J.enabled!==!1?"[enabled]":"[disabled]"),console.log(M.join(" "))}break}case"remove":{let j=N[0];if(!j)console.error("Error: remove requires an account ID."),W(),process.exit(1);let J=Y(),D=await C(J),M=D?D.has(j):!1,T=!1;if(await X((Q)=>{let G=Q.accounts.findIndex((L)=>L.id===j);if(G===-1)return Q;return Q.accounts.splice(G,1),T=!0,Q},J,{allowDrop:[j]}),!(T||M))console.error(`No account with id "${j}".`),process.exit(1);console.log(`Removed account ${j}.`);break}default:console.error(`Unknown command: ${H}`),W(),process.exit(1)}}if(Z.main==Z.module)R().catch((z)=>{console.error(z instanceof Error?z.message:String(z)),process.exit(1)});export{V as openBrowserForLogin};
@@ -1,3 +0,0 @@
1
- export declare function hasWebSocketResponsesLiteMetadata(body: BodyInit | null | undefined): boolean;
2
- export declare function sanitizeHttpFallbackBody(body: BodyInit | null | undefined): string | ArrayBuffer | ArrayBufferView<ArrayBuffer> | Blob | FormData | ReadableStream<any> | URLSearchParams | null | undefined;
3
- export declare function sanitizeHttpFallbackInit(init: RequestInit | undefined): RequestInit | undefined;
@@ -1,88 +0,0 @@
1
- import { type loadAccounts as defaultLoadAccounts } from './core/accounts';
2
- import type { CacheKeepManager, CacheKeepWindow } from './core/cachekeep';
3
- import type { QuotaManager } from './core/quota-manager';
4
- import type { RefreshAllQuotaResult } from './core/refresh-all-quota';
5
- import { type RunResetCreditResult } from './core/reset-credits';
6
- import type { ApplyRequest, ApplyResult, CommandModalName, OpenDialogPayload } from './rpc/protocol';
7
- export declare const OPENAI_QUOTA_COMMAND_NAME = "openai-quota";
8
- export declare const OPENAI_ACCOUNT_COMMAND_NAME = "openai-account";
9
- export declare const OPENAI_ROUTING_COMMAND_NAME = "openai-routing";
10
- export declare const OPENAI_KILLSWITCH_COMMAND_NAME = "openai-killswitch";
11
- export declare const OPENAI_DUMP_COMMAND_NAME = "openai-dump";
12
- export declare const OPENAI_LOGGING_COMMAND_NAME = "openai-logging";
13
- export declare const OPENAI_CACHEKEEP_COMMAND_NAME = "openai-cachekeep";
14
- export declare const OPENAI_RESET_COMMAND_NAME = "openai-reset";
15
- export declare const MODAL_COMMANDS: CommandModalName[];
16
- export interface CommandContext {
17
- accountStoragePath: string;
18
- quotaManager: QuotaManager;
19
- loadAccounts: typeof defaultLoadAccounts;
20
- client: {
21
- auth: {
22
- set: (input: {
23
- path: {
24
- id: string;
25
- };
26
- body: {
27
- type: string;
28
- access?: string;
29
- refresh: string;
30
- expires?: number;
31
- };
32
- }) => Promise<unknown>;
33
- };
34
- };
35
- /** Session ID for pushNotification delivery. */
36
- sessionId?: string;
37
- /** If set, pushNotification is wired up and can deliver feedback to the user. */
38
- notify?: (payload: OpenDialogPayload) => void;
39
- /** Refresh the sidebar-state file so the TUI modal shows current data. */
40
- refreshSidebar?: () => Promise<void>;
41
- /** Actively poll wham/usage for all accounts (main + fallbacks). */
42
- refreshAllQuota?: () => Promise<RefreshAllQuotaResult[]>;
43
- /** Prompt-cache cachekeep manager. Set when the command is wired. */
44
- cacheKeepManager?: CacheKeepManager | null;
45
- /** Updates the live loader's persisted-enabled cachekeep gate. */
46
- setCacheKeepEnabled?: (enabled: boolean) => void;
47
- /** Updates the live loader's persisted-subagent cachekeep gate. */
48
- setCacheKeepSubagents?: (enabled: boolean) => void;
49
- /** Updates the live loader's main-agent idle-cap bypass gate. */
50
- setCacheKeepSustain?: (enabled: boolean) => void;
51
- /** Updates the live loader's clock-hour warm window. undefined = no window. */
52
- setCacheKeepWindow?: (window: CacheKeepWindow | undefined) => void;
53
- /** Clears only the sticky account assignment for one OpenCode session. */
54
- clearStickyRouting?: (sessionId: string) => Promise<boolean>;
55
- /** Resolves the current session's usable sticky account, if one exists. */
56
- getStickyRouting?: (sessionId: string) => Promise<string | undefined>;
57
- resolveResetTarget?: (accountKey: string) => Promise<ResetTargetIdentity>;
58
- fetchImpl?: typeof fetch;
59
- now?: () => number;
60
- randomUUID?: () => string;
61
- refreshResetTargetQuota?: (accountKey: string) => Promise<RefreshAllQuotaResult>;
62
- }
63
- export interface ResetTargetIdentity {
64
- accountKey: string;
65
- label: string;
66
- accessToken: string;
67
- chatgptAccountId?: string;
68
- }
69
- type ResetCommandContext = CommandContext & Required<Pick<CommandContext, 'resolveResetTarget' | 'fetchImpl' | 'now' | 'randomUUID' | 'refreshResetTargetQuota'>>;
70
- export declare function renderResetCoordinatorResult(result: RunResetCreditResult, ctx: ResetCommandContext, boundChatgptAccountId?: string): Promise<OpenDialogPayload>;
71
- /**
72
- * Strip credential-shaped fields from a dialog payload's knobs.
73
- *
74
- * Knobs are returned across the loopback RPC and JSON-serialized to the TUI, so
75
- * a knob is a published surface. Individual commands project their own knobs
76
- * deliberately (see accountKnob), but this is the boundary backstop: a future
77
- * command that returns a stored object directly cannot leak credentials even if
78
- * the projection is forgotten, because nothing credential-shaped survives here.
79
- *
80
- * Scrub rather than throw. A rejected dialog is a visible outage for a live
81
- * command, while a scrubbed one keeps working with the leak removed; the warning
82
- * is what gets the projection fixed. Recurses into nested objects and arrays,
83
- * since the account list arrives as an array of records.
84
- */
85
- export declare function scrubKnobs(value: unknown, path: string, found: string[]): unknown;
86
- export declare function buildDialogPayload(command: CommandModalName, args: string, ctx: CommandContext): Promise<OpenDialogPayload>;
87
- export declare function applyCommand(request: ApplyRequest, ctx: CommandContext): Promise<ApplyResult>;
88
- export {};
package/dist/config.d.ts DELETED
@@ -1,47 +0,0 @@
1
- export declare const DEFAULT_CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
2
- /** Shape of ~/.config/opencode/openai-auth.json (all fields optional). */
3
- export interface OpenAIAuthConfig {
4
- /** Inject the native web_search tool to keep the Codex prompt cache stable. Default true. */
5
- webSearch?: boolean;
6
- /** Use the WebSocket transport for /responses instead of plain HTTP. Default false. */
7
- webSockets?: boolean;
8
- /** Use the hand-rolled raw TCP/TLS WebSocket client (incremental streaming). Default false. */
9
- rawWebSocket?: boolean;
10
- /** Use Codex's Responses Lite request shape. Default false. */
11
- responsesLite?: boolean;
12
- /** Dump final Codex request bodies for cache debugging. Default false. */
13
- dump?: boolean | {
14
- enabled?: boolean;
15
- };
16
- /** Directory for request dumps. Defaults to the OS temp directory. */
17
- dumpDir?: string;
18
- /** Codex-compatible Responses endpoint. Defaults to ChatGPT's Codex backend. */
19
- codexApiEndpoint?: string;
20
- }
21
- export interface ResolvedSettings {
22
- webSearch: boolean;
23
- webSockets: boolean;
24
- rawWebSocket: boolean;
25
- responsesLite: boolean;
26
- dump: boolean;
27
- dumpDir: string;
28
- codexApiEndpoint: string;
29
- }
30
- export declare function getConfigDir(): string;
31
- export declare function getConfigPath(): string;
32
- /**
33
- * Resolved settings, memoized per process.
34
- *
35
- * Env and the config file are read once because neither changes under a running
36
- * process — except through a command that writes the config itself. Those
37
- * commands must call `refreshSettings()`, or the process keeps serving the
38
- * values it read at startup while the file on disk says otherwise.
39
- */
40
- export declare function getSettings(): ResolvedSettings;
41
- /**
42
- * Drop the memoized settings after a command writes the config file, so the
43
- * running process picks the change up without a restart.
44
- */
45
- export declare function refreshSettings(): ResolvedSettings;
46
- /** Test-only: drop the memoized settings so a later getSettings() re-reads env + config. */
47
- export declare function resetSettingsForTest(): void;
@@ -1,25 +0,0 @@
1
- /**
2
- * Where the account store lives.
3
- *
4
- * This is the ONLY definition. It used to be duplicated verbatim in both
5
- * `accounts.ts` and `refresh-file-lock.ts`, because `accounts.ts` imports the
6
- * lock and the reverse import would have been a cycle. Two copies of a path
7
- * resolver is a bad trade for that: the lock and the write must agree on the
8
- * exact file, and if the copies ever drifted, a writer would take a lock on one
9
- * path while writing another — mutual exclusion silently lost on a file holding
10
- * credentials. Nothing would fail a test, since each copy works on its own.
11
- *
12
- * This module imports nothing from either side, so both can depend on it.
13
- */
14
- export declare const ACCOUNT_FILE_NAME = "openai-auth.json";
15
- export declare const ACCOUNT_STATE_FILE_NAME = "openai-auth-state.json";
16
- export declare function getAccountStoragePath(): string;
17
- /** Derive the state-file path from the config path without reading env vars. */
18
- export declare function deriveStatePath(configPath: string): string;
19
- /**
20
- * Detect path aliases without requiring either file to exist. This is defense
21
- * in depth: hardlinks and bind mounts can still make distinct paths share a
22
- * file, because neither is distinguishable through pathname identity.
23
- */
24
- export declare function accountPathsCollide(configPath: string, statePath: string, platform?: NodeJS.Platform): boolean;
25
- export declare function getAccountStatePath(configPath?: string): string;