@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.
- package/README.md +9 -5
- package/dist/index-301y4qa1.js +2 -0
- package/dist/index-338z7171.js +211 -0
- package/dist/index-5y4vzdf8.js +2 -0
- package/dist/{index-zxqb5ydj.js → index-9ehhb051.js} +1 -1
- package/dist/{index-zg1x8sty.js → index-jwn4r3sw.js} +1 -1
- package/dist/{index-9jpc8yct.js → index-sdt2d2ra.js} +1 -1
- package/dist/index-w42s0g6m.js +2 -0
- package/dist/index.d.ts +213 -36
- package/dist/index.js +59 -154
- package/dist/internal-Y7QNVDJT.d.ts +908 -0
- package/dist/quota-normalize-3qffywcm.js +1 -0
- package/dist/rpc/port-file.d.ts +11 -9
- package/dist/rpc/port-file.js +1 -1
- package/dist/rpc/protocol.d.ts +2 -21
- package/dist/rpc/rpc-client.d.ts +7 -4
- package/dist/rpc/rpc-client.js +1 -1
- package/dist/rpc/rpc-dir.d.ts +7 -5
- package/dist/rpc/rpc-dir.js +1 -1
- package/dist/sidebar-state-B98sERYt.d.ts +219 -0
- package/dist/sidebar-state.d.ts +2 -171
- package/dist/sidebar-state.js +1 -1
- package/dist/{token-bvp0y166.js → token-9823y0pc.js} +1 -1
- package/dist/token-util-ypgz7rge.js +1 -0
- package/dist/tui-preferences.d.ts +27 -26
- package/dist/tui-preferences.js +1 -1
- package/dist/tui.d.ts +42 -19
- package/package.json +8 -14
- package/src/tui/entry.mjs +2 -2
- package/src/tui-compiled/{core/account-paths.ts → raw/core-account-paths.ts} +29 -18
- package/src/tui-compiled/raw/core-custody-state.ts +243 -0
- package/src/tui-compiled/raw/logger.ts +53 -0
- package/src/tui-compiled/{rpc/port-file.ts → raw/rpc-port-file.ts} +1 -1
- package/src/tui-compiled/raw/rpc-protocol.ts +12 -0
- package/src/{rpc/rpc-client.ts → tui-compiled/raw/rpc-rpc-client.ts} +2 -2
- package/src/{sidebar-state.ts → tui-compiled/raw/sidebar-state.ts} +142 -13
- package/src/{tui/command-dialogs.tsx → tui-compiled/raw/tui-command-dialogs.tsx} +94 -44
- package/src/{tui.tsx → tui-compiled/raw/tui.tsx} +149 -28
- package/src/{core/account-paths.ts → tui-compiled/runtime/core-account-paths.ts} +29 -18
- package/src/tui-compiled/runtime/core-custody-state.ts +243 -0
- package/src/tui-compiled/runtime/logger.ts +53 -0
- package/src/{rpc/port-file.ts → tui-compiled/runtime/rpc-port-file.ts} +1 -1
- package/src/tui-compiled/runtime/rpc-protocol.ts +12 -0
- package/src/tui-compiled/{rpc/rpc-client.ts → runtime/rpc-rpc-client.ts} +2 -2
- package/src/tui-compiled/{sidebar-state.ts → runtime/sidebar-state.ts} +142 -13
- package/src/tui-compiled/{tui/command-dialogs.tsx → runtime/tui-command-dialogs.tsx} +73 -37
- package/src/tui-compiled/{tui.tsx → runtime/tui.tsx} +251 -153
- package/src/tui-compiled/shared/internal.ts +6 -0
- package/src/{logger.ts → tui-compiled/shared/logger.ts} +91 -23
- package/src/tui-compiled/shared/paths.ts +33 -0
- package/src/{core → tui-compiled/shared}/refresh-file-lock.ts +7 -4
- package/dist/cli.d.ts +0 -2
- package/dist/cli.js +0 -15
- package/dist/codex-http.d.ts +0 -3
- package/dist/commands.d.ts +0 -88
- package/dist/config.d.ts +0 -47
- package/dist/core/account-paths.d.ts +0 -25
- package/dist/core/accounts.d.ts +0 -330
- package/dist/core/atomic-write.d.ts +0 -1
- package/dist/core/background-quota-refresh.d.ts +0 -46
- package/dist/core/backoff.d.ts +0 -53
- package/dist/core/cachekeep.d.ts +0 -118
- package/dist/core/oauth.d.ts +0 -138
- package/dist/core/provider.d.ts +0 -70
- package/dist/core/quota-manager.d.ts +0 -192
- package/dist/core/refresh-all-quota.d.ts +0 -86
- package/dist/core/refresh-file-lock.d.ts +0 -12
- package/dist/core/reset-credits.d.ts +0 -116
- package/dist/core/sticky-routing.d.ts +0 -43
- package/dist/dump.d.ts +0 -20
- package/dist/hosted-web-search.d.ts +0 -5
- package/dist/index-87145jkw.js +0 -2
- package/dist/index-8f1200qx.js +0 -6
- package/dist/index-cfjed1st.js +0 -89
- package/dist/index-nrvjr97q.js +0 -3
- package/dist/index-qaggaze1.js +0 -2
- package/dist/index-sdcpzbnk.js +0 -2
- package/dist/logger.d.ts +0 -22
- package/dist/model-costs.d.ts +0 -29
- package/dist/prompt-context.d.ts +0 -19
- package/dist/quota-normalize-dvwtmy7f.js +0 -1
- package/dist/quota-normalize.d.ts +0 -43
- package/dist/raw-ws-bun.d.ts +0 -40
- package/dist/raw-ws-node.d.ts +0 -37
- package/dist/raw-ws-upgrade.d.ts +0 -2
- package/dist/raw-ws.d.ts +0 -3
- package/dist/response-stream-error.d.ts +0 -12
- package/dist/rpc/notifications.d.ts +0 -5
- package/dist/rpc/rpc-server.d.ts +0 -17
- package/dist/token-util-jcj7k7pa.js +0 -1
- package/dist/tui/command-dialogs.d.ts +0 -21
- package/dist/util/error.d.ts +0 -1
- package/dist/util/open-url.d.ts +0 -6
- package/dist/util/proxy-env.d.ts +0 -4
- package/dist/util/record.d.ts +0 -1
- package/dist/util/stable-json.d.ts +0 -1
- package/dist/util/uuid-v7.d.ts +0 -1
- package/dist/version.d.ts +0 -1
- package/dist/ws-pool.d.ts +0 -57
- package/dist/ws.d.ts +0 -71
- package/src/rpc/notifications.ts +0 -54
- package/src/rpc/protocol.ts +0 -33
- package/src/rpc/rpc-server.ts +0 -172
- package/src/tui-compiled/core/refresh-file-lock.ts +0 -381
- package/src/tui-compiled/logger.ts +0 -196
- package/src/tui-compiled/rpc/protocol.ts +0 -33
- package/src/util/error.ts +0 -9
- package/src/util/open-url.ts +0 -30
- package/src/util/proxy-env.ts +0 -42
- package/src/util/record.ts +0 -3
- package/src/util/stable-json.ts +0 -15
- package/src/util/uuid-v7.ts +0 -18
- /package/src/{rpc/rpc-dir.ts → tui-compiled/raw/rpc-rpc-dir.ts} +0 -0
- /package/src/tui-compiled/{tui-preferences.ts → raw/tui-preferences.ts} +0 -0
- /package/src/tui-compiled/{rpc/rpc-dir.ts → runtime/rpc-rpc-dir.ts} +0 -0
- /package/src/{tui-preferences.ts → tui-compiled/runtime/tui-preferences.ts} +0 -0
- /package/src/tui-compiled/{util → shared/util}/error.ts +0 -0
- /package/src/tui-compiled/{util → shared/util}/open-url.ts +0 -0
|
@@ -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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
35
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
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};
|
package/dist/codex-http.d.ts
DELETED
|
@@ -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;
|
package/dist/commands.d.ts
DELETED
|
@@ -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;
|