@namzu/cli 13.0.0 → 14.1.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 +13 -2
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +79 -21
- package/dist/commands/login.js.map +1 -1
- package/dist/doctor/checks/credentials.d.ts.map +1 -1
- package/dist/doctor/checks/credentials.js +7 -1
- package/dist/doctor/checks/credentials.js.map +1 -1
- package/dist/integrations/providers/codex-device-login.d.ts +27 -0
- package/dist/integrations/providers/codex-device-login.d.ts.map +1 -0
- package/dist/integrations/providers/codex-device-login.js +195 -0
- package/dist/integrations/providers/codex-device-login.js.map +1 -0
- package/dist/integrations/providers/codex-oauth.d.ts +10 -0
- package/dist/integrations/providers/codex-oauth.d.ts.map +1 -0
- package/dist/integrations/providers/codex-oauth.js +95 -0
- package/dist/integrations/providers/codex-oauth.js.map +1 -0
- package/dist/integrations/providers/credential-store.d.ts +23 -4
- package/dist/integrations/providers/credential-store.d.ts.map +1 -1
- package/dist/integrations/providers/credential-store.js +125 -19
- package/dist/integrations/providers/credential-store.js.map +1 -1
- package/dist/integrations/providers/discover.d.ts +39 -13
- package/dist/integrations/providers/discover.d.ts.map +1 -1
- package/dist/integrations/providers/discover.js +122 -44
- package/dist/integrations/providers/discover.js.map +1 -1
- package/dist/integrations/providers/harness-credentials.d.ts +36 -0
- package/dist/integrations/providers/harness-credentials.d.ts.map +1 -0
- package/dist/integrations/providers/harness-credentials.js +146 -0
- package/dist/integrations/providers/harness-credentials.js.map +1 -0
- package/dist/integrations/providers/identity.d.ts +8 -15
- package/dist/integrations/providers/identity.d.ts.map +1 -1
- package/dist/integrations/providers/identity.js +8 -15
- package/dist/integrations/providers/identity.js.map +1 -1
- package/dist/integrations/providers/index.d.ts +6 -3
- package/dist/integrations/providers/index.d.ts.map +1 -1
- package/dist/integrations/providers/index.js +5 -2
- package/dist/integrations/providers/index.js.map +1 -1
- package/dist/integrations/providers/oauth.d.ts +2 -2
- package/dist/integrations/providers/oauth.d.ts.map +1 -1
- package/dist/integrations/providers/oauth.js +8 -5
- package/dist/integrations/providers/oauth.js.map +1 -1
- package/dist/integrations/providers/register.d.ts.map +1 -1
- package/dist/integrations/providers/register.js +9 -1
- package/dist/integrations/providers/register.js.map +1 -1
- package/dist/integrations/providers/registry.d.ts +8 -1
- package/dist/integrations/providers/registry.d.ts.map +1 -1
- package/dist/integrations/providers/registry.js +29 -0
- package/dist/integrations/providers/registry.js.map +1 -1
- package/dist/tui/App.d.ts +5 -5
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +257 -98
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/CopyPicker.d.ts +8 -0
- package/dist/tui/CopyPicker.d.ts.map +1 -0
- package/dist/tui/CopyPicker.js +20 -0
- package/dist/tui/CopyPicker.js.map +1 -0
- package/dist/tui/Picker.d.ts +12 -3
- package/dist/tui/Picker.d.ts.map +1 -1
- package/dist/tui/Picker.js +88 -27
- package/dist/tui/Picker.js.map +1 -1
- package/dist/tui/agent.d.ts +2 -5
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +112 -17
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/copy-targets.d.ts +23 -0
- package/dist/tui/copy-targets.d.ts.map +1 -0
- package/dist/tui/copy-targets.js +189 -0
- package/dist/tui/copy-targets.js.map +1 -0
- package/dist/tui/login-prompt.d.ts +5 -0
- package/dist/tui/login-prompt.d.ts.map +1 -1
- package/dist/tui/login-prompt.js +14 -0
- package/dist/tui/login-prompt.js.map +1 -1
- package/dist/tui/model-choices.d.ts.map +1 -1
- package/dist/tui/model-choices.js +6 -1
- package/dist/tui/model-choices.js.map +1 -1
- package/dist/tui/slashCommands.d.ts +1 -1
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +2 -2
- package/dist/tui/slashCommands.js.map +1 -1
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ description: >-
|
|
|
6
6
|
you get. Interactive sessions, headless runs that stream structured events,
|
|
7
7
|
and a doctor that reports what the host can actually do.
|
|
8
8
|
tags: [readme, package, cli, agent]
|
|
9
|
-
timestamp: 2026-08-
|
|
9
|
+
timestamp: 2026-08-22T00:00:00Z
|
|
10
10
|
status: active
|
|
11
11
|
diataxis: reference
|
|
12
12
|
-->
|
|
@@ -64,9 +64,20 @@ probes for.
|
|
|
64
64
|
```bash
|
|
65
65
|
namzu # interactive session in the current directory
|
|
66
66
|
namzu doctor # what this host can actually do, and what is missing
|
|
67
|
-
namzu login
|
|
67
|
+
namzu login claude # create a Namzu-owned Claude subscription session
|
|
68
|
+
namzu login codex # create a Namzu-owned ChatGPT subscription session
|
|
68
69
|
```
|
|
69
70
|
|
|
71
|
+
On startup, Namzu first reuses usable `Claude` and `Codex` sessions already owned
|
|
72
|
+
by their installed command-line clients. With no saved choice, one signed-in
|
|
73
|
+
subscription starts directly; if both are available, a narrowed picker asks
|
|
74
|
+
which one to use and proceeds with its default model. These borrowed credentials
|
|
75
|
+
remain read-only and are never copied into `~/.namzu`. A Namzu-owned sign-in is
|
|
76
|
+
needed only when no usable device session exists or when you explicitly want a
|
|
77
|
+
separate login. API keys remain optional alternatives through environment
|
|
78
|
+
variables or the session-only credential picker, and detecting one does not hide
|
|
79
|
+
the subscription sign-in action.
|
|
80
|
+
|
|
70
81
|
Repository policy stays live for the whole session. The CLI starts with the
|
|
71
82
|
applicable `AGENTS.md` chain, discovers nested instruction files after
|
|
72
83
|
successful reads, writes and edits, and labels every file with its directory
|
package/dist/commands/login.d.ts
CHANGED
|
@@ -31,8 +31,10 @@
|
|
|
31
31
|
* browser that lands on this machine; standard input takes the address pasted
|
|
32
32
|
* back from a browser somewhere else. Whichever answers first wins.
|
|
33
33
|
*/
|
|
34
|
+
import { type SubscriptionProviderId } from '../integrations/providers/index.js';
|
|
34
35
|
import type { CommandDef } from './types.js';
|
|
35
36
|
interface LoginFlags {
|
|
37
|
+
readonly provider?: SubscriptionProviderId;
|
|
36
38
|
readonly noBrowser: boolean;
|
|
37
39
|
readonly timeoutMs: number;
|
|
38
40
|
readonly unknown: readonly string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAKH,OAAO,EAEN,KAAK,sBAAsB,EAO3B,MAAM,oCAAoC,CAAA;AAQ3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAsB5C,UAAU,UAAU;IACnB,QAAQ,CAAC,QAAQ,CAAC,EAAE,sBAAsB,CAAA;IAC1C,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAsCnE;AAoCD,eAAO,MAAM,YAAY,EAAE,UAuG1B,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,UAiB3B,CAAA"}
|
package/dist/commands/login.js
CHANGED
|
@@ -33,27 +33,30 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { createInterface } from 'node:readline';
|
|
35
35
|
import { EXIT_FAIL, EXIT_OK, EXIT_USAGE } from '../exit-codes.js';
|
|
36
|
-
import { beginSubscriptionLogin,
|
|
37
|
-
import { describeLoginOutcome, describeLoginStart, describeLogout } from '../tui/login-prompt.js';
|
|
36
|
+
import { beginCodexDeviceLogin, beginSubscriptionLogin, clearAllStoredCredentials, credentialsPath, readStoredCodexCredential, readStoredSubscriptionCredential, } from '../integrations/providers/index.js';
|
|
37
|
+
import { describeCodexDeviceLoginStart, describeLoginOutcome, describeLoginStart, describeLogout, } from '../tui/login-prompt.js';
|
|
38
38
|
import { openInBrowser } from '../tui/open-browser.js';
|
|
39
|
-
const LOGIN_HELP =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
--
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
address
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
39
|
+
const LOGIN_HELP = [
|
|
40
|
+
'Usage: namzu login <claude|codex> [options]',
|
|
41
|
+
'',
|
|
42
|
+
'Sign in with a provider subscription and store the credential on this machine.',
|
|
43
|
+
'',
|
|
44
|
+
'Options:',
|
|
45
|
+
' --no-browser Do not try to launch a browser; just print the address.',
|
|
46
|
+
' --timeout <seconds> Give up waiting after this long (default: 300).',
|
|
47
|
+
' -h, --help Show this help.',
|
|
48
|
+
'',
|
|
49
|
+
'Claude sign-in opens a browser callback; on a remote machine, paste the final',
|
|
50
|
+
'callback address into this terminal. Codex sign-in prints a device code and',
|
|
51
|
+
'polls while you approve it in the browser.',
|
|
52
|
+
'',
|
|
53
|
+
'The credential is written to ~/.namzu/credentials.json, readable only by your',
|
|
54
|
+
"account. Run 'namzu logout' to remove it.",
|
|
55
|
+
].join('\n');
|
|
54
56
|
const DEFAULT_TIMEOUT_SECONDS = 300;
|
|
55
57
|
export function parseLoginFlags(argv) {
|
|
56
58
|
let noBrowser = false;
|
|
59
|
+
let provider;
|
|
57
60
|
let timeoutMs = DEFAULT_TIMEOUT_SECONDS * 1_000;
|
|
58
61
|
const unknown = [];
|
|
59
62
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -76,10 +79,24 @@ export function parseLoginFlags(argv) {
|
|
|
76
79
|
timeoutMs = seconds * 1_000;
|
|
77
80
|
continue;
|
|
78
81
|
}
|
|
82
|
+
if (arg === 'claude' || arg === 'anthropic') {
|
|
83
|
+
if (provider)
|
|
84
|
+
unknown.push(arg);
|
|
85
|
+
else
|
|
86
|
+
provider = 'anthropic';
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (arg === 'codex' || arg === 'chatgpt') {
|
|
90
|
+
if (provider)
|
|
91
|
+
unknown.push(arg);
|
|
92
|
+
else
|
|
93
|
+
provider = 'codex';
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
79
96
|
if (arg !== undefined)
|
|
80
97
|
unknown.push(arg);
|
|
81
98
|
}
|
|
82
|
-
return { noBrowser, timeoutMs, unknown };
|
|
99
|
+
return { provider, noBrowser, timeoutMs, unknown };
|
|
83
100
|
}
|
|
84
101
|
/**
|
|
85
102
|
* Resolve with the first NON-BLANK line standard input offers, or never.
|
|
@@ -129,6 +146,44 @@ export const loginCommand = {
|
|
|
129
146
|
});
|
|
130
147
|
return EXIT_USAGE;
|
|
131
148
|
}
|
|
149
|
+
if (!flags.provider) {
|
|
150
|
+
ctx.formatter.print({
|
|
151
|
+
text: `Choose which subscription Namzu should own:\n namzu login claude\n namzu login codex\n\nAPI keys remain optional alternatives.\n\n${LOGIN_HELP}`,
|
|
152
|
+
});
|
|
153
|
+
return EXIT_USAGE;
|
|
154
|
+
}
|
|
155
|
+
if (flags.provider === 'codex') {
|
|
156
|
+
let login;
|
|
157
|
+
try {
|
|
158
|
+
login = await beginCodexDeviceLogin();
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
ctx.formatter.print({
|
|
162
|
+
text: `Could not start Codex sign-in: ${error instanceof Error ? error.message : String(error)}`,
|
|
163
|
+
});
|
|
164
|
+
return EXIT_FAIL;
|
|
165
|
+
}
|
|
166
|
+
ctx.formatter.print({
|
|
167
|
+
text: describeCodexDeviceLoginStart({
|
|
168
|
+
url: login.url,
|
|
169
|
+
userCode: login.userCode,
|
|
170
|
+
browserOpened: flags.noBrowser ? false : openInBrowser(login.url),
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
const timeout = new Promise((resolve) => setTimeout(() => resolve({
|
|
174
|
+
ok: false,
|
|
175
|
+
reason: 'Timed out waiting for Codex sign-in. Nothing was stored.',
|
|
176
|
+
}), flags.timeoutMs).unref());
|
|
177
|
+
const outcome = await Promise.race([login.waitForCompletion(), timeout]);
|
|
178
|
+
login.cancel();
|
|
179
|
+
ctx.formatter.print({
|
|
180
|
+
text: describeLoginOutcome(outcome, {
|
|
181
|
+
retry: 'namzu login codex',
|
|
182
|
+
remove: 'namzu logout',
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
return outcome.ok ? EXIT_OK : EXIT_FAIL;
|
|
186
|
+
}
|
|
132
187
|
let login;
|
|
133
188
|
try {
|
|
134
189
|
login = await beginSubscriptionLogin();
|
|
@@ -158,7 +213,10 @@ export const loginCommand = {
|
|
|
158
213
|
stop.abort();
|
|
159
214
|
login.cancel();
|
|
160
215
|
ctx.formatter.print({
|
|
161
|
-
text: describeLoginOutcome(outcome, {
|
|
216
|
+
text: describeLoginOutcome(outcome, {
|
|
217
|
+
retry: 'namzu login claude',
|
|
218
|
+
remove: 'namzu logout',
|
|
219
|
+
}),
|
|
162
220
|
});
|
|
163
221
|
return outcome.ok ? EXIT_OK : EXIT_FAIL;
|
|
164
222
|
},
|
|
@@ -168,9 +226,9 @@ export const logoutCommand = {
|
|
|
168
226
|
description: 'Remove the subscription credential namzu stored on this machine.',
|
|
169
227
|
handler: async ({ ctx }) => {
|
|
170
228
|
const path = credentialsPath();
|
|
171
|
-
const had = readStoredSubscriptionCredential() !== null;
|
|
229
|
+
const had = readStoredSubscriptionCredential() !== null || readStoredCodexCredential() !== null;
|
|
172
230
|
try {
|
|
173
|
-
|
|
231
|
+
clearAllStoredCredentials();
|
|
174
232
|
}
|
|
175
233
|
catch (err) {
|
|
176
234
|
ctx.formatter.print({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AACjE,OAAO,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,YAAY,CAAA;AAIhE;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,EAAE,
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/doctor/checks/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAqB,MAAM,YAAY,CAAA;AAIhE;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAgDpC,CAAA"}
|
|
@@ -36,7 +36,7 @@ export const credentialSourcesCheck = {
|
|
|
36
36
|
return {
|
|
37
37
|
status: 'warn',
|
|
38
38
|
message: 'no LLM credential found',
|
|
39
|
-
remediation: '
|
|
39
|
+
remediation: 'Namzu no longer reads the secrets file. It first reuses current Claude and Codex sessions on this device, then subscriptions signed in with `namzu login claude|codex`. API keys remain optional alternatives through ANTHROPIC_API_KEY or OPENAI_API_KEY; local Ollama and LM Studio servers are also detected.',
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
const lines = detected.map((d) => {
|
|
@@ -45,10 +45,16 @@ export const credentialSourcesCheck = {
|
|
|
45
45
|
return `${d.entry.id} (env · ${d.source.envName})`;
|
|
46
46
|
case 'keychain':
|
|
47
47
|
return `${d.entry.id} (keychain · ${d.source.service})`;
|
|
48
|
+
case 'claude-file':
|
|
49
|
+
return `${d.entry.id} (Claude session · ${d.source.path})`;
|
|
50
|
+
case 'codex-file':
|
|
51
|
+
return `${d.entry.id} (Codex session · ${d.source.path})`;
|
|
48
52
|
case 'stored':
|
|
49
53
|
return `${d.entry.id} (signed in · ${d.source.path})`;
|
|
50
54
|
case 'probe':
|
|
51
55
|
return `${d.entry.id} (local · ${d.source.url.replace(/^https?:\/\//, '')})`;
|
|
56
|
+
case 'session':
|
|
57
|
+
return `${d.entry.id} (typed · current session)`;
|
|
52
58
|
}
|
|
53
59
|
});
|
|
54
60
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/doctor/checks/credentials.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAE5E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAgB;IAClD,EAAE,EAAE,uBAAuB;IAC3B,QAAQ,EAAE,WAAW;IACrB,GAAG,EAAE,KAAK,IAAgC,EAAE;QAC3C,IAAI,QAAuD,CAAA;QAC3D,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,iBAAiB,EAAE,CAAA;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,oEAAoE;YACpE,sEAAsE;YACtE,OAAO;gBACN,MAAM,EAAE,cAAc;gBACtB,OAAO,EAAE,gCAAgC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;aAC3F,CAAA;QACF,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACN,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,yBAAyB;gBAClC,WAAW,EACV,
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../../src/doctor/checks/credentials.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAA;AAE5E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAgB;IAClD,EAAE,EAAE,uBAAuB;IAC3B,QAAQ,EAAE,WAAW;IACrB,GAAG,EAAE,KAAK,IAAgC,EAAE;QAC3C,IAAI,QAAuD,CAAA;QAC3D,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,iBAAiB,EAAE,CAAA;QACrC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,oEAAoE;YACpE,sEAAsE;YACtE,OAAO;gBACN,MAAM,EAAE,cAAc;gBACtB,OAAO,EAAE,gCAAgC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;aAC3F,CAAA;QACF,CAAC;QAED,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO;gBACN,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,yBAAyB;gBAClC,WAAW,EACV,kTAAkT;aACnT,CAAA;QACF,CAAC;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACvB,KAAK,KAAK;oBACT,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,CAAA;gBACnD,KAAK,UAAU;oBACd,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,gBAAgB,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,CAAA;gBACxD,KAAK,aAAa;oBACjB,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAA;gBAC3D,KAAK,YAAY;oBAChB,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,qBAAqB,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAA;gBAC1D,KAAK,QAAQ;oBACZ,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,iBAAiB,CAAC,CAAC,MAAM,CAAC,IAAI,GAAG,CAAA;gBACtD,KAAK,OAAO;oBACX,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,aAAa,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,GAAG,CAAA;gBAC7E,KAAK,SAAS;oBACb,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,4BAA4B,CAAA;YAClD,CAAC;QACF,CAAC,CAAC,CAAA;QACF,OAAO;YACN,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,GAAG,QAAQ,CAAC,MAAM,kCAAkC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SAC/E,CAAA;IACF,CAAC;CACD,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Namzu-owned ChatGPT/Codex device authorization for machines without Codex installed. */
|
|
2
|
+
import { type CodexOAuthCredential } from './harness-credentials.js';
|
|
3
|
+
export declare const CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
4
|
+
export declare const CODEX_AUTH_ORIGIN = "https://auth.openai.com";
|
|
5
|
+
export type CodexDeviceLoginOutcome = {
|
|
6
|
+
readonly ok: true;
|
|
7
|
+
readonly credential: CodexOAuthCredential;
|
|
8
|
+
readonly storedAt: string;
|
|
9
|
+
} | {
|
|
10
|
+
readonly ok: false;
|
|
11
|
+
readonly reason: string;
|
|
12
|
+
};
|
|
13
|
+
export interface CodexDeviceLogin {
|
|
14
|
+
readonly url: string;
|
|
15
|
+
readonly userCode: string;
|
|
16
|
+
waitForCompletion(): Promise<CodexDeviceLoginOutcome>;
|
|
17
|
+
cancel(): void;
|
|
18
|
+
}
|
|
19
|
+
export interface CodexDeviceLoginOptions {
|
|
20
|
+
readonly home?: string;
|
|
21
|
+
readonly fetch?: typeof fetch;
|
|
22
|
+
readonly signal?: AbortSignal;
|
|
23
|
+
readonly authOrigin?: string;
|
|
24
|
+
readonly pollTimeoutMs?: number;
|
|
25
|
+
}
|
|
26
|
+
export declare function beginCodexDeviceLogin(options?: CodexDeviceLoginOptions): Promise<CodexDeviceLogin>;
|
|
27
|
+
//# sourceMappingURL=codex-device-login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-device-login.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/codex-device-login.ts"],"names":[],"mappings":"AAAA,2FAA2F;AAG3F,OAAO,EAAE,KAAK,oBAAoB,EAA6B,MAAM,0BAA0B,CAAA;AAE/F,eAAO,MAAM,qBAAqB,iCAAiC,CAAA;AACnE,eAAO,MAAM,iBAAiB,4BAA4B,CAAA;AAE1D,MAAM,MAAM,uBAAuB,GAChC;IACA,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAA;IACjB,QAAQ,CAAC,UAAU,EAAE,oBAAoB,CAAA;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CACxB,GACD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAElD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,iBAAiB,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAAA;IACrD,MAAM,IAAI,IAAI,CAAA;CACd;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAC/B;AAyMD,wBAAsB,qBAAqB,CAC1C,OAAO,GAAE,uBAA4B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CA2B3B"}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/** Namzu-owned ChatGPT/Codex device authorization for machines without Codex installed. */
|
|
2
|
+
import { writeStoredCodexCredential } from './credential-store.js';
|
|
3
|
+
import { codexCredentialFromTokens } from './harness-credentials.js';
|
|
4
|
+
export const CODEX_OAUTH_CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann';
|
|
5
|
+
export const CODEX_AUTH_ORIGIN = 'https://auth.openai.com';
|
|
6
|
+
function asRecord(value) {
|
|
7
|
+
return typeof value === 'object' && value !== null ? value : null;
|
|
8
|
+
}
|
|
9
|
+
async function withSignal(operation, signal) {
|
|
10
|
+
signal.throwIfAborted();
|
|
11
|
+
let rejectAbort = () => { };
|
|
12
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
13
|
+
rejectAbort = reject;
|
|
14
|
+
});
|
|
15
|
+
const onAbort = () => rejectAbort(signal.reason);
|
|
16
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
17
|
+
try {
|
|
18
|
+
return await Promise.race([operation, aborted]);
|
|
19
|
+
}
|
|
20
|
+
finally {
|
|
21
|
+
signal.removeEventListener('abort', onAbort);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function parseJson(response, signal) {
|
|
25
|
+
const value = asRecord(await withSignal(response.json(), signal));
|
|
26
|
+
if (!value)
|
|
27
|
+
throw new Error('The sign-in service returned an invalid response.');
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
async function requestUserCode(fetchFn, origin, signal) {
|
|
31
|
+
const response = await withSignal(fetchFn(`${origin}/api/accounts/deviceauth/usercode`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: {
|
|
34
|
+
'content-type': 'application/json',
|
|
35
|
+
accept: 'application/json',
|
|
36
|
+
},
|
|
37
|
+
body: JSON.stringify({ client_id: CODEX_OAUTH_CLIENT_ID }),
|
|
38
|
+
signal,
|
|
39
|
+
}), signal);
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error(`The Codex device sign-in service refused the request (HTTP ${response.status}).`);
|
|
42
|
+
}
|
|
43
|
+
const body = await parseJson(response, signal);
|
|
44
|
+
const deviceAuthId = body.device_auth_id;
|
|
45
|
+
const userCode = body.user_code ?? body.usercode;
|
|
46
|
+
const seconds = Number(body.interval);
|
|
47
|
+
if (typeof deviceAuthId !== 'string' ||
|
|
48
|
+
deviceAuthId.length === 0 ||
|
|
49
|
+
typeof userCode !== 'string' ||
|
|
50
|
+
userCode.length === 0 ||
|
|
51
|
+
!Number.isFinite(seconds) ||
|
|
52
|
+
seconds < 0) {
|
|
53
|
+
throw new Error('The Codex device sign-in service returned an incomplete response.');
|
|
54
|
+
}
|
|
55
|
+
return { deviceAuthId, userCode, intervalMs: Math.max(10, seconds * 1_000) };
|
|
56
|
+
}
|
|
57
|
+
async function delay(ms, signal) {
|
|
58
|
+
let timer;
|
|
59
|
+
try {
|
|
60
|
+
await withSignal(new Promise((resolve) => {
|
|
61
|
+
timer = setTimeout(resolve, ms);
|
|
62
|
+
}), signal);
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
if (timer !== undefined)
|
|
66
|
+
clearTimeout(timer);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function complete(code, options, signal) {
|
|
70
|
+
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
71
|
+
const origin = (options.authOrigin ?? CODEX_AUTH_ORIGIN).replace(/\/$/, '');
|
|
72
|
+
const deadlineAt = Date.now() + (options.pollTimeoutMs ?? 15 * 60_000);
|
|
73
|
+
let authorization = null;
|
|
74
|
+
while (Date.now() < deadlineAt) {
|
|
75
|
+
signal.throwIfAborted();
|
|
76
|
+
const response = await withSignal(fetchFn(`${origin}/api/accounts/deviceauth/token`, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: {
|
|
79
|
+
'content-type': 'application/json',
|
|
80
|
+
accept: 'application/json',
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify({
|
|
83
|
+
device_auth_id: code.deviceAuthId,
|
|
84
|
+
user_code: code.userCode,
|
|
85
|
+
}),
|
|
86
|
+
signal,
|
|
87
|
+
}), signal);
|
|
88
|
+
if (response.ok) {
|
|
89
|
+
authorization = await parseJson(response, signal);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (response.status !== 403 && response.status !== 404) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
reason: `The Codex device sign-in was refused (HTTP ${response.status}). Nothing was stored.`,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
await delay(code.intervalMs, signal);
|
|
99
|
+
}
|
|
100
|
+
if (!authorization) {
|
|
101
|
+
return {
|
|
102
|
+
ok: false,
|
|
103
|
+
reason: 'The Codex device code expired. Nothing was stored.',
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const authorizationCode = authorization.authorization_code;
|
|
107
|
+
const verifier = authorization.code_verifier;
|
|
108
|
+
if (typeof authorizationCode !== 'string' ||
|
|
109
|
+
authorizationCode.length === 0 ||
|
|
110
|
+
typeof verifier !== 'string' ||
|
|
111
|
+
verifier.length === 0) {
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
reason: 'The Codex device sign-in returned no exchange code. Nothing was stored.',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const redirectUri = `${origin}/deviceauth/callback`;
|
|
118
|
+
const form = new URLSearchParams({
|
|
119
|
+
grant_type: 'authorization_code',
|
|
120
|
+
code: authorizationCode,
|
|
121
|
+
redirect_uri: redirectUri,
|
|
122
|
+
client_id: CODEX_OAUTH_CLIENT_ID,
|
|
123
|
+
code_verifier: verifier,
|
|
124
|
+
});
|
|
125
|
+
const exchanged = await withSignal(fetchFn(`${origin}/oauth/token`, {
|
|
126
|
+
method: 'POST',
|
|
127
|
+
headers: {
|
|
128
|
+
'content-type': 'application/x-www-form-urlencoded',
|
|
129
|
+
accept: 'application/json',
|
|
130
|
+
},
|
|
131
|
+
body: form.toString(),
|
|
132
|
+
signal,
|
|
133
|
+
}), signal);
|
|
134
|
+
if (!exchanged.ok) {
|
|
135
|
+
return {
|
|
136
|
+
ok: false,
|
|
137
|
+
reason: `The Codex token exchange was refused (HTTP ${exchanged.status}). Nothing was stored.`,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
const tokens = await parseJson(exchanged, signal);
|
|
141
|
+
const accessToken = tokens.access_token;
|
|
142
|
+
const refreshToken = tokens.refresh_token;
|
|
143
|
+
const credential = typeof accessToken === 'string'
|
|
144
|
+
? codexCredentialFromTokens({
|
|
145
|
+
accessToken,
|
|
146
|
+
...(typeof refreshToken === 'string' ? { refreshToken } : {}),
|
|
147
|
+
})
|
|
148
|
+
: null;
|
|
149
|
+
if (!credential) {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
reason: 'The Codex token exchange did not identify an account. Nothing was stored.',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
signal.throwIfAborted();
|
|
156
|
+
try {
|
|
157
|
+
const storedAt = writeStoredCodexCredential(credential, options.home);
|
|
158
|
+
return { ok: true, credential, storedAt };
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
return {
|
|
162
|
+
ok: false,
|
|
163
|
+
reason: `Signed in to Codex, but the credential could not be stored privately: ${error instanceof Error ? error.message : String(error)}`,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export async function beginCodexDeviceLogin(options = {}) {
|
|
168
|
+
options.signal?.throwIfAborted();
|
|
169
|
+
const owner = new AbortController();
|
|
170
|
+
const signal = options.signal ? AbortSignal.any([options.signal, owner.signal]) : owner.signal;
|
|
171
|
+
const origin = (options.authOrigin ?? CODEX_AUTH_ORIGIN).replace(/\/$/, '');
|
|
172
|
+
const userCode = await requestUserCode(options.fetch ?? globalThis.fetch, origin, signal);
|
|
173
|
+
let completion;
|
|
174
|
+
return {
|
|
175
|
+
url: `${origin}/codex/device`,
|
|
176
|
+
userCode: userCode.userCode,
|
|
177
|
+
waitForCompletion: () => {
|
|
178
|
+
completion ??= complete(userCode, options, signal).catch((error) => {
|
|
179
|
+
if (signal.aborted) {
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
reason: 'The Codex sign-in was cancelled. Nothing was stored.',
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
ok: false,
|
|
187
|
+
reason: `Could not complete Codex sign-in: ${error instanceof Error ? error.message : String(error)}`,
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
return completion;
|
|
191
|
+
},
|
|
192
|
+
cancel: () => owner.abort(new Error('The Codex sign-in attempt was cancelled.')),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=codex-device-login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-device-login.js","sourceRoot":"","sources":["../../../src/integrations/providers/codex-device-login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Refresh for a Codex credential owned by Namzu's credential store. */
|
|
2
|
+
import { type StoredCodexCredential } from './credential-store.js';
|
|
3
|
+
export interface StoredCodexRefreshOptions {
|
|
4
|
+
readonly home?: string;
|
|
5
|
+
readonly fetch?: typeof fetch;
|
|
6
|
+
readonly authOrigin?: string;
|
|
7
|
+
readonly now?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function ensureFreshStoredCodexCredential(signal?: AbortSignal, options?: StoredCodexRefreshOptions): Promise<StoredCodexCredential>;
|
|
10
|
+
//# sourceMappingURL=codex-oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-oauth.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/codex-oauth.ts"],"names":[],"mappings":"AAAA,wEAAwE;AAGxE,OAAO,EACN,KAAK,qBAAqB,EAG1B,MAAM,uBAAuB,CAAA;AAM9B,MAAM,WAAW,yBAAyB;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CACrB;AAqBD,wBAAsB,gCAAgC,CACrD,MAAM,CAAC,EAAE,WAAW,EACpB,OAAO,GAAE,yBAA8B,GACrC,OAAO,CAAC,qBAAqB,CAAC,CAoFhC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/** Refresh for a Codex credential owned by Namzu's credential store. */
|
|
2
|
+
import { CODEX_AUTH_ORIGIN, CODEX_OAUTH_CLIENT_ID } from './codex-device-login.js';
|
|
3
|
+
import { readStoredCodexCredential, replaceStoredCodexCredential, } from './credential-store.js';
|
|
4
|
+
import { codexCredentialFromTokens } from './harness-credentials.js';
|
|
5
|
+
import { CredentialPublicationError, CredentialWithdrawnError } from './oauth.js';
|
|
6
|
+
const REFRESH_WINDOW_MS = 5 * 60_000;
|
|
7
|
+
function asRecord(value) {
|
|
8
|
+
return typeof value === 'object' && value !== null ? value : null;
|
|
9
|
+
}
|
|
10
|
+
async function withSignal(operation, signal) {
|
|
11
|
+
signal.throwIfAborted();
|
|
12
|
+
let rejectAbort = () => { };
|
|
13
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
14
|
+
rejectAbort = reject;
|
|
15
|
+
});
|
|
16
|
+
const onAbort = () => rejectAbort(signal.reason);
|
|
17
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
18
|
+
try {
|
|
19
|
+
return await Promise.race([operation, aborted]);
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
signal.removeEventListener('abort', onAbort);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function ensureFreshStoredCodexCredential(signal, options = {}) {
|
|
26
|
+
signal?.throwIfAborted();
|
|
27
|
+
const current = readStoredCodexCredential(options.home);
|
|
28
|
+
if (!current) {
|
|
29
|
+
throw new CredentialWithdrawnError('The Codex subscription Namzu stored was removed. Sign in again or choose another provider.');
|
|
30
|
+
}
|
|
31
|
+
if (current.expiresAt === undefined ||
|
|
32
|
+
current.expiresAt - (options.now ?? Date.now()) > REFRESH_WINDOW_MS) {
|
|
33
|
+
return current;
|
|
34
|
+
}
|
|
35
|
+
if (!current.refreshToken) {
|
|
36
|
+
throw new CredentialWithdrawnError('The Codex subscription expired without a refresh grant. Sign in again.');
|
|
37
|
+
}
|
|
38
|
+
const deadline = AbortSignal.timeout(30_000);
|
|
39
|
+
const requestSignal = signal ? AbortSignal.any([signal, deadline]) : deadline;
|
|
40
|
+
let response;
|
|
41
|
+
try {
|
|
42
|
+
response = await withSignal((options.fetch ?? globalThis.fetch)(`${(options.authOrigin ?? CODEX_AUTH_ORIGIN).replace(/\/$/, '')}/oauth/token`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: {
|
|
45
|
+
'content-type': 'application/json',
|
|
46
|
+
accept: 'application/json',
|
|
47
|
+
},
|
|
48
|
+
body: JSON.stringify({
|
|
49
|
+
client_id: CODEX_OAUTH_CLIENT_ID,
|
|
50
|
+
grant_type: 'refresh_token',
|
|
51
|
+
refresh_token: current.refreshToken,
|
|
52
|
+
}),
|
|
53
|
+
signal: requestSignal,
|
|
54
|
+
}), requestSignal);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (signal?.aborted)
|
|
58
|
+
throw signal.reason;
|
|
59
|
+
throw new CredentialPublicationError({ cause: error });
|
|
60
|
+
}
|
|
61
|
+
if (!response.ok) {
|
|
62
|
+
throw new CredentialWithdrawnError(`The Codex subscription could not be refreshed (HTTP ${response.status}). Sign in again.`);
|
|
63
|
+
}
|
|
64
|
+
const body = asRecord(await withSignal(response.json(), requestSignal));
|
|
65
|
+
if (!body) {
|
|
66
|
+
throw new CredentialWithdrawnError('The Codex refresh service returned an invalid credential. Sign in again.');
|
|
67
|
+
}
|
|
68
|
+
const accessToken = body.access_token;
|
|
69
|
+
const refreshToken = body.refresh_token;
|
|
70
|
+
const refreshed = typeof accessToken === 'string'
|
|
71
|
+
? codexCredentialFromTokens({
|
|
72
|
+
accessToken,
|
|
73
|
+
refreshToken: typeof refreshToken === 'string' ? refreshToken : current.refreshToken,
|
|
74
|
+
accountId: current.accountId,
|
|
75
|
+
})
|
|
76
|
+
: null;
|
|
77
|
+
if (!refreshed || refreshed.accountId !== current.accountId) {
|
|
78
|
+
throw new CredentialWithdrawnError('The refreshed Codex credential did not belong to the signed-in account. Sign in again.');
|
|
79
|
+
}
|
|
80
|
+
signal?.throwIfAborted();
|
|
81
|
+
let result;
|
|
82
|
+
try {
|
|
83
|
+
result = replaceStoredCodexCredential(current, refreshed, options.home);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
throw new CredentialPublicationError({ cause: error });
|
|
87
|
+
}
|
|
88
|
+
if (!result.replaced) {
|
|
89
|
+
if (!result.current)
|
|
90
|
+
throw new CredentialWithdrawnError();
|
|
91
|
+
return result.current;
|
|
92
|
+
}
|
|
93
|
+
return refreshed;
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=codex-oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codex-oauth.js","sourceRoot":"","sources":["../../../src/integrations/providers/codex-oauth.ts"],"names":[],"mappings":"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"}
|