@heyditto/cli 2.14.1 → 2.16.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 +31 -0
- package/dist/agents/codexapp.d.ts +60 -0
- package/dist/agents/codexapp.js +475 -0
- package/dist/agents/codexapp.js.map +1 -0
- package/dist/agents/grok.d.ts +48 -0
- package/dist/agents/grok.js +152 -0
- package/dist/agents/grok.js.map +1 -0
- package/dist/agents/launch.js +64 -8
- package/dist/agents/launch.js.map +1 -1
- package/dist/agents/types.d.ts +1 -1
- package/dist/agents/types.js +1 -1
- package/dist/agents/types.js.map +1 -1
- package/dist/api.d.ts +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands.d.ts +0 -1
- package/dist/commands.js +15 -9
- package/dist/commands.js.map +1 -1
- package/dist/remote/catalog.js +38 -0
- package/dist/remote/catalog.js.map +1 -1
- package/dist/remote/controller.js +25 -2
- package/dist/remote/controller.js.map +1 -1
- package/dist/remote/headless.d.ts +7 -0
- package/dist/remote/headless.js +4 -1
- package/dist/remote/headless.js.map +1 -1
- package/dist/remote/protocol.d.ts +1 -1
- package/dist/store.d.ts +20 -0
- package/dist/store.js.map +1 -1
- package/dist/teleport/commands.js +6 -4
- package/dist/teleport/commands.js.map +1 -1
- package/dist/teleport/harness.d.ts +2 -0
- package/dist/teleport/harness.js +19 -0
- package/dist/teleport/harness.js.map +1 -1
- package/dist/teleport/restore.js +2 -1
- package/dist/teleport/restore.js.map +1 -1
- package/dist/teleport/types.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -148,6 +148,7 @@ heyditto apps endpoints list|attach|billing|detach <app> [<endpoint>]
|
|
|
148
148
|
heyditto receipts [--leg ditto|byok|covered] [--app <app_id>] [--days <n>]
|
|
149
149
|
heyditto claude [options] [-- <claude args>]
|
|
150
150
|
heyditto codex [options] [-- <codex args>]
|
|
151
|
+
heyditto codex-app [--endpoint <slug>] [--model <id>] [--unset]
|
|
151
152
|
heyditto sessions [--json] [--all]
|
|
152
153
|
heyditto sessions rm <id>
|
|
153
154
|
heyditto session new [<name>...] [--id <id>]
|
|
@@ -442,6 +443,36 @@ How the wiring works:
|
|
|
442
443
|
`ditto` model provider via `-c` overrides (nothing is written to
|
|
443
444
|
`~/.codex/config.toml`) with the key in `DITTO_INFERENCE_API_KEY`.
|
|
444
445
|
|
|
446
|
+
### `codex-app`
|
|
447
|
+
|
|
448
|
+
`heyditto codex-app` wires the **Codex desktop app** (ChatGPT.app) to one of
|
|
449
|
+
your inference endpoints, so its models — GLM Flash and friends — work in the
|
|
450
|
+
app behind its own **"Sign in with an API key"** screen. Unlike the CLI, the
|
|
451
|
+
app cannot be handed environment variables (a Dock-launched app inherits
|
|
452
|
+
none), so the wiring is file-based in the `~/.codex` directory the app shares
|
|
453
|
+
with the CLI:
|
|
454
|
+
|
|
455
|
+
- `openai_base_url` in `~/.codex/config.toml` repoints the built-in `openai`
|
|
456
|
+
provider (the Responses wire the gateway speaks) at your endpoint;
|
|
457
|
+
- the minted endpoint key lands in `~/.codex/auth.json` as the API-key login,
|
|
458
|
+
the same place the app's sign-in screen writes.
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
heyditto codex-app # sign in, pick an endpoint, wire the app
|
|
462
|
+
heyditto codex-app --endpoint my-endpoint # route through a specific endpoint
|
|
463
|
+
heyditto codex-app --model glm-5.3-flash # pin the app's model
|
|
464
|
+
heyditto codex-app --dry-run # show what would be written
|
|
465
|
+
heyditto codex-app --unset # restore the previous wiring, revoke the key
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
The command also enables the endpoint's model picker (`--codex-models on`),
|
|
469
|
+
so the app's model picker lists the endpoint's models. A previous login
|
|
470
|
+
(especially a ChatGPT-plan one) is backed up to `auth.json.pre-ditto` and
|
|
471
|
+
confirmed before it is replaced; `--unset` restores it. The key is long-lived
|
|
472
|
+
(unlike `heyditto codex`'s per-session keys) and is revoked by `--unset` or
|
|
473
|
+
rotated on the next run. Both files are shared with the Codex CLI, so a bare
|
|
474
|
+
`codex` run routes through Ditto too; `heyditto codex` is unaffected.
|
|
475
|
+
|
|
445
476
|
### `endpoints`
|
|
446
477
|
|
|
447
478
|
Manage the inference endpoints the launchers route through — a CLI mirror of
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
/**
|
|
3
|
+
* `heyditto codex-app`: point the Codex desktop app (ChatGPT.app) at a Ditto
|
|
4
|
+
* inference endpoint, so its models — GLM Flash and friends — are usable
|
|
5
|
+
* through the app's own "Sign in with an API key" path.
|
|
6
|
+
*
|
|
7
|
+
* The app shares ~/.codex with the Codex CLI and, unlike the CLI, cannot be
|
|
8
|
+
* handed environment variables (a Dock-launched app inherits none), so the
|
|
9
|
+
* wiring is file-based:
|
|
10
|
+
*
|
|
11
|
+
* - `openai_base_url` in ~/.codex/config.toml repoints the built-in `openai`
|
|
12
|
+
* provider — the Responses wire, which the gateway speaks — at the
|
|
13
|
+
* endpoint's gateway;
|
|
14
|
+
* - the endpoint key goes into ~/.codex/auth.json as OPENAI_API_KEY, the
|
|
15
|
+
* same file the app's "Sign in with an API key" screen writes. Riding the
|
|
16
|
+
* built-in provider's auth is what makes that screen the only sign-in the
|
|
17
|
+
* user needs; a custom provider's `env_key` would have nothing to read in
|
|
18
|
+
* an app launched from the Dock.
|
|
19
|
+
*
|
|
20
|
+
* Both files are shared with the Codex CLI: a bare `codex` run routes
|
|
21
|
+
* through Ditto too. `heyditto codex` is unaffected — it injects its own
|
|
22
|
+
* provider with -c overrides. `--unset` restores what was there before.
|
|
23
|
+
*/
|
|
24
|
+
export declare const CODEX_APP_MARKER = "# added by `heyditto codex-app`";
|
|
25
|
+
/** ~/.codex, or $CODEX_HOME (the same resolution Codex itself uses). */
|
|
26
|
+
export declare function codexHome(env?: NodeJS.ProcessEnv): string;
|
|
27
|
+
export type CodexAuthKind = "absent" | "api-key" | "chatgpt" | "unknown";
|
|
28
|
+
/**
|
|
29
|
+
* What ~/.codex/auth.json holds. `chatgpt` is a ChatGPT-plan login (tokens);
|
|
30
|
+
* replacing it signs the CLI and the app out of that plan, so it is backed
|
|
31
|
+
* up and confirmed first.
|
|
32
|
+
*/
|
|
33
|
+
export declare function classifyAuthJson(raw: string | undefined): CodexAuthKind;
|
|
34
|
+
/** The top-level string value of `key`, or undefined when absent/unparsable. */
|
|
35
|
+
export declare function topLevelString(raw: string | undefined, key: string): string | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Sets a top-level string key, replacing an existing assignment in place or
|
|
38
|
+
* inserting one before the first table header (with `comment` above it).
|
|
39
|
+
* Callers parse the result before writing it anywhere.
|
|
40
|
+
*/
|
|
41
|
+
export declare function upsertTopLevelString(raw: string | undefined, key: string, value: string, comment?: string): string;
|
|
42
|
+
/** Removes the top-level assignment of `key` (and a codex-app marker comment above it). */
|
|
43
|
+
export declare function removeTopLevelString(raw: string | undefined, key: string): string;
|
|
44
|
+
export interface CodexAppOptions {
|
|
45
|
+
endpoint?: string;
|
|
46
|
+
budget?: string;
|
|
47
|
+
expires?: string;
|
|
48
|
+
model?: string;
|
|
49
|
+
models?: boolean;
|
|
50
|
+
name?: string;
|
|
51
|
+
yes?: boolean;
|
|
52
|
+
dryRun?: boolean;
|
|
53
|
+
unset?: boolean;
|
|
54
|
+
showKey?: boolean;
|
|
55
|
+
}
|
|
56
|
+
/** Removes the codex-app wiring: restores config.toml and auth.json, revokes the key. */
|
|
57
|
+
export declare function unsetCodexApp(): Promise<void>;
|
|
58
|
+
export declare function runCodexApp(options: CodexAppOptions): Promise<void>;
|
|
59
|
+
/** Registers `codex-app` on the program (which must have enablePositionalOptions()). */
|
|
60
|
+
export declare function registerCodexAppCommand(program: Command, addExamples: (c: Command, ex: string) => Command): void;
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import { chmod, copyFile, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { createInterface } from "node:readline/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { parse as parseToml } from "smol-toml";
|
|
6
|
+
import { Option } from "commander";
|
|
7
|
+
import { createKey, findEndpoint, listEndpoints, revokeKey, updateEndpoint, } from "../api.js";
|
|
8
|
+
import { openInBrowser } from "../browser.js";
|
|
9
|
+
import { endpointURL, resolveApiKey } from "../config.js";
|
|
10
|
+
import { deviceLogin } from "../device-login.js";
|
|
11
|
+
import { readStoredAuth, saveLogin, updateStoredAuth } from "../store.js";
|
|
12
|
+
import { err as c } from "../ui.js";
|
|
13
|
+
import { assertEndpointActive, pickEndpoint } from "./launch.js";
|
|
14
|
+
import { DEFAULT_LAUNCH_EXPIRY, KEY_EXPIRIES } from "./types.js";
|
|
15
|
+
/**
|
|
16
|
+
* `heyditto codex-app`: point the Codex desktop app (ChatGPT.app) at a Ditto
|
|
17
|
+
* inference endpoint, so its models — GLM Flash and friends — are usable
|
|
18
|
+
* through the app's own "Sign in with an API key" path.
|
|
19
|
+
*
|
|
20
|
+
* The app shares ~/.codex with the Codex CLI and, unlike the CLI, cannot be
|
|
21
|
+
* handed environment variables (a Dock-launched app inherits none), so the
|
|
22
|
+
* wiring is file-based:
|
|
23
|
+
*
|
|
24
|
+
* - `openai_base_url` in ~/.codex/config.toml repoints the built-in `openai`
|
|
25
|
+
* provider — the Responses wire, which the gateway speaks — at the
|
|
26
|
+
* endpoint's gateway;
|
|
27
|
+
* - the endpoint key goes into ~/.codex/auth.json as OPENAI_API_KEY, the
|
|
28
|
+
* same file the app's "Sign in with an API key" screen writes. Riding the
|
|
29
|
+
* built-in provider's auth is what makes that screen the only sign-in the
|
|
30
|
+
* user needs; a custom provider's `env_key` would have nothing to read in
|
|
31
|
+
* an app launched from the Dock.
|
|
32
|
+
*
|
|
33
|
+
* Both files are shared with the Codex CLI: a bare `codex` run routes
|
|
34
|
+
* through Ditto too. `heyditto codex` is unaffected — it injects its own
|
|
35
|
+
* provider with -c overrides. `--unset` restores what was there before.
|
|
36
|
+
*/
|
|
37
|
+
export const CODEX_APP_MARKER = "# added by `heyditto codex-app`";
|
|
38
|
+
/** ~/.codex, or $CODEX_HOME (the same resolution Codex itself uses). */
|
|
39
|
+
export function codexHome(env = process.env) {
|
|
40
|
+
const home = env.CODEX_HOME?.trim();
|
|
41
|
+
return home && home.length > 0 ? home : path.join(os.homedir(), ".codex");
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* What ~/.codex/auth.json holds. `chatgpt` is a ChatGPT-plan login (tokens);
|
|
45
|
+
* replacing it signs the CLI and the app out of that plan, so it is backed
|
|
46
|
+
* up and confirmed first.
|
|
47
|
+
*/
|
|
48
|
+
export function classifyAuthJson(raw) {
|
|
49
|
+
if (raw === undefined || raw.trim() === "")
|
|
50
|
+
return "absent";
|
|
51
|
+
try {
|
|
52
|
+
const parsed = JSON.parse(raw);
|
|
53
|
+
if (typeof parsed.OPENAI_API_KEY === "string" && parsed.OPENAI_API_KEY.length > 0)
|
|
54
|
+
return "api-key";
|
|
55
|
+
if (parsed.tokens != null || parsed.id_token != null || parsed.refresh_token != null)
|
|
56
|
+
return "chatgpt";
|
|
57
|
+
return "unknown";
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return "unknown";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** The top-level string value of `key`, or undefined when absent/unparsable. */
|
|
64
|
+
export function topLevelString(raw, key) {
|
|
65
|
+
if (raw === undefined || raw.trim() === "")
|
|
66
|
+
return undefined;
|
|
67
|
+
try {
|
|
68
|
+
const parsed = parseToml(raw);
|
|
69
|
+
const value = parsed[key];
|
|
70
|
+
return typeof value === "string" ? value : undefined;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function assignmentLine(lines, key) {
|
|
77
|
+
// Top-level keys are unindented by convention; restricting the match to
|
|
78
|
+
// column 0 keeps a same-named key inside some table from being rewritten.
|
|
79
|
+
// The indented fallback exists for hand-formatted configs; every write is
|
|
80
|
+
// parsed back before it lands, so the fallback can only move an odd file
|
|
81
|
+
// from parsable to parsable-with-our-value, never to broken.
|
|
82
|
+
let idx = lines.findIndex((l) => new RegExp(`^${key}\\s*=`).test(l));
|
|
83
|
+
if (idx !== -1)
|
|
84
|
+
return idx;
|
|
85
|
+
return lines.findIndex((l) => new RegExp(`^\\s+${key}\\s*=`).test(l));
|
|
86
|
+
}
|
|
87
|
+
function firstTableLine(lines) {
|
|
88
|
+
return lines.findIndex((l) => /^\s*\[.+\]\s*(#.*)?$/.test(l));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Sets a top-level string key, replacing an existing assignment in place or
|
|
92
|
+
* inserting one before the first table header (with `comment` above it).
|
|
93
|
+
* Callers parse the result before writing it anywhere.
|
|
94
|
+
*/
|
|
95
|
+
export function upsertTopLevelString(raw, key, value, comment) {
|
|
96
|
+
const text = raw ?? "";
|
|
97
|
+
const lines = text.split("\n");
|
|
98
|
+
const escaped = JSON.stringify(value);
|
|
99
|
+
const idx = assignmentLine(lines, key);
|
|
100
|
+
if (idx !== -1) {
|
|
101
|
+
lines[idx] = `${key} = ${escaped}`;
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
104
|
+
const entry = comment ? [comment, `${key} = ${escaped}`] : [`${key} = ${escaped}`];
|
|
105
|
+
const table = firstTableLine(lines);
|
|
106
|
+
if (table === -1) {
|
|
107
|
+
const trimmed = text.replace(/\s+$/, "");
|
|
108
|
+
return trimmed === "" ? `${entry.join("\n")}\n` : `${trimmed}\n${entry.join("\n")}\n`;
|
|
109
|
+
}
|
|
110
|
+
lines.splice(table, 0, ...entry);
|
|
111
|
+
return lines.join("\n");
|
|
112
|
+
}
|
|
113
|
+
/** Removes the top-level assignment of `key` (and a codex-app marker comment above it). */
|
|
114
|
+
export function removeTopLevelString(raw, key) {
|
|
115
|
+
if (raw === undefined)
|
|
116
|
+
return "";
|
|
117
|
+
const lines = raw.split("\n");
|
|
118
|
+
const idx = assignmentLine(lines, key);
|
|
119
|
+
if (idx === -1)
|
|
120
|
+
return raw;
|
|
121
|
+
let start = idx;
|
|
122
|
+
if (start > 0 && lines[start - 1].trim() === CODEX_APP_MARKER)
|
|
123
|
+
start -= 1;
|
|
124
|
+
lines.splice(start, idx + 1 - start);
|
|
125
|
+
return lines.join("\n");
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* What sat under `key` before codex-app wrote it: a value already in the
|
|
129
|
+
* file that is not ours belongs to someone else and is preserved as-is; a
|
|
130
|
+
* value equal to ours restores the recorded previous one (null = none).
|
|
131
|
+
*/
|
|
132
|
+
function previousValue(raw, key, ours, recorded) {
|
|
133
|
+
const existing = topLevelString(raw, key);
|
|
134
|
+
if (existing === undefined)
|
|
135
|
+
return null;
|
|
136
|
+
if (ours !== undefined && existing === ours)
|
|
137
|
+
return recorded ?? null;
|
|
138
|
+
return existing;
|
|
139
|
+
}
|
|
140
|
+
async function readMaybe(filePath) {
|
|
141
|
+
try {
|
|
142
|
+
return await readFile(filePath, "utf8");
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (err.code === "ENOENT")
|
|
146
|
+
return undefined;
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/** Copies `fromPath` to `toPath` once; never overwrites an earlier backup. */
|
|
151
|
+
async function backupOnce(fromPath, toPath) {
|
|
152
|
+
if ((await readMaybe(toPath)) !== undefined)
|
|
153
|
+
return false;
|
|
154
|
+
if ((await readMaybe(fromPath)) === undefined)
|
|
155
|
+
return false;
|
|
156
|
+
await copyFile(fromPath, toPath);
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
function log(line) {
|
|
160
|
+
process.stderr.write(`${c("dim", "ditto:")} ${line}\n`);
|
|
161
|
+
}
|
|
162
|
+
function interactive() {
|
|
163
|
+
return Boolean(process.stdin.isTTY && process.stderr.isTTY);
|
|
164
|
+
}
|
|
165
|
+
function parseBudget(raw) {
|
|
166
|
+
if (raw === undefined)
|
|
167
|
+
return undefined;
|
|
168
|
+
const n = Number(raw.replace(/[_,]/g, ""));
|
|
169
|
+
if (!Number.isInteger(n) || n <= 0)
|
|
170
|
+
throw new Error(`--budget must be a positive integer token count, got "${raw}"`);
|
|
171
|
+
return n;
|
|
172
|
+
}
|
|
173
|
+
function parseExpiry(raw) {
|
|
174
|
+
const value = (raw ?? DEFAULT_LAUNCH_EXPIRY).trim();
|
|
175
|
+
if (KEY_EXPIRIES.includes(value))
|
|
176
|
+
return value;
|
|
177
|
+
throw new Error(`--expires must be one of: ${KEY_EXPIRIES.join(", ")}`);
|
|
178
|
+
}
|
|
179
|
+
async function ask(question) {
|
|
180
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
181
|
+
try {
|
|
182
|
+
return (await rl.question(question)).trim();
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
rl.close();
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** Yes/no prompt with Enter defaulting to no — a destructive default is the one thing it must not have. */
|
|
189
|
+
async function confirmYes(question) {
|
|
190
|
+
const answer = (await ask(`${question} [y/N] `)).toLowerCase();
|
|
191
|
+
return answer === "y" || answer === "yes";
|
|
192
|
+
}
|
|
193
|
+
async function resolveEndpointFor(options, selected) {
|
|
194
|
+
const catalog = await listEndpoints();
|
|
195
|
+
const endpoints = catalog.endpoints;
|
|
196
|
+
const stored = (await readStoredAuth())?.defaultEndpoint;
|
|
197
|
+
const wanted = options.endpoint?.trim();
|
|
198
|
+
if (wanted) {
|
|
199
|
+
const match = findEndpoint(endpoints, wanted);
|
|
200
|
+
if (match)
|
|
201
|
+
return { endpoint: match, catalog };
|
|
202
|
+
throw new Error(`no endpoint named "${wanted}". Available: ${endpoints.map((e) => e.slug).join(", ")}`);
|
|
203
|
+
}
|
|
204
|
+
if (selected) {
|
|
205
|
+
const match = findEndpoint(endpoints, selected.id) ?? findEndpoint(endpoints, selected.slug);
|
|
206
|
+
if (match)
|
|
207
|
+
return { endpoint: match, catalog };
|
|
208
|
+
log(`endpoint "${selected.slug}" picked in the browser is not in your list; pick another`);
|
|
209
|
+
}
|
|
210
|
+
if (stored?.trim()) {
|
|
211
|
+
const match = findEndpoint(endpoints, stored);
|
|
212
|
+
if (match)
|
|
213
|
+
return { endpoint: match, catalog };
|
|
214
|
+
log(`default endpoint "${stored.trim()}" no longer exists; pick another`);
|
|
215
|
+
}
|
|
216
|
+
if (endpoints.length === 0) {
|
|
217
|
+
throw new Error("you have no inference endpoints yet. Create one with `heyditto endpoints create`.");
|
|
218
|
+
}
|
|
219
|
+
if (endpoints.length === 1)
|
|
220
|
+
return { endpoint: endpoints[0], catalog };
|
|
221
|
+
return { endpoint: await pickEndpoint(endpoints, stored), catalog };
|
|
222
|
+
}
|
|
223
|
+
async function ensureLogin() {
|
|
224
|
+
const { key } = await resolveApiKey();
|
|
225
|
+
if (key)
|
|
226
|
+
return undefined;
|
|
227
|
+
if (!interactive()) {
|
|
228
|
+
await listEndpoints(); // throws the shared "no Ditto API key configured" error
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
log("no Ditto login yet — opening your browser to sign in and pick an endpoint for the Codex app.");
|
|
232
|
+
const result = await deviceLogin({
|
|
233
|
+
intent: "codex",
|
|
234
|
+
onCode: (userCode, url) => {
|
|
235
|
+
process.stderr.write(`\n ${url}\n\n Code: ${userCode}\n\n`);
|
|
236
|
+
openInBrowser(url);
|
|
237
|
+
process.stderr.write("Waiting for approval in the browser (Ctrl+C to cancel)…\n");
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
await saveLogin(result.apiKey, result.setDefault && result.endpoint ? { defaultEndpoint: result.endpoint.slug } : {});
|
|
241
|
+
log(`logged in${result.endpoint ? `; endpoint ${result.endpoint.slug}${result.setDefault ? " saved as default" : ""}` : ""}`);
|
|
242
|
+
return result.endpoint;
|
|
243
|
+
}
|
|
244
|
+
/** Restores a key codex-app took over: previous value back, or ours removed. */
|
|
245
|
+
function restoreKey(raw, key, ours, previous) {
|
|
246
|
+
const current = topLevelString(raw, key);
|
|
247
|
+
if (current === undefined)
|
|
248
|
+
return undefined;
|
|
249
|
+
if (ours !== undefined && current !== ours)
|
|
250
|
+
return undefined; // changed since; leave it
|
|
251
|
+
return previous ? upsertTopLevelString(raw, key, previous) : removeTopLevelString(raw, key);
|
|
252
|
+
}
|
|
253
|
+
/** Removes the codex-app wiring: restores config.toml and auth.json, revokes the key. */
|
|
254
|
+
export async function unsetCodexApp() {
|
|
255
|
+
const stored = await readStoredAuth();
|
|
256
|
+
const record = stored?.codexApp;
|
|
257
|
+
if (!record) {
|
|
258
|
+
throw new Error("no codex-app wiring found (nothing `heyditto codex-app` wrote is recorded)");
|
|
259
|
+
}
|
|
260
|
+
const home = codexHome();
|
|
261
|
+
const configPath = path.join(home, "config.toml");
|
|
262
|
+
const authPath = path.join(home, "auth.json");
|
|
263
|
+
const authBackupPath = `${authPath}.pre-ditto`;
|
|
264
|
+
const configRaw = await readMaybe(configPath);
|
|
265
|
+
let configText = restoreKey(configRaw, "openai_base_url", record.baseUrl, record.previousBaseUrl) ?? configRaw;
|
|
266
|
+
configText = restoreKey(configText, "forced_login_method", record.forcedLogin ?? "api", record.previousForcedLogin ?? null) ?? configText;
|
|
267
|
+
if (record.model !== undefined) {
|
|
268
|
+
configText = restoreKey(configText, "model", record.model, record.previousModel) ?? configText;
|
|
269
|
+
}
|
|
270
|
+
if (configText !== undefined && configText !== configRaw) {
|
|
271
|
+
await writeFile(configPath, configText, { mode: 0o600 });
|
|
272
|
+
log(`restored ${configPath}`);
|
|
273
|
+
}
|
|
274
|
+
const authRaw = await readMaybe(authPath);
|
|
275
|
+
const kind = classifyAuthJson(authRaw);
|
|
276
|
+
if ((await readMaybe(authBackupPath)) !== undefined) {
|
|
277
|
+
await rename(authBackupPath, authPath);
|
|
278
|
+
log(`restored the previous login from ${authBackupPath}`);
|
|
279
|
+
}
|
|
280
|
+
else if (kind === "absent") {
|
|
281
|
+
// nothing to restore
|
|
282
|
+
}
|
|
283
|
+
else if (kind === "api-key" && record.key !== undefined && authRaw === `${JSON.stringify({ OPENAI_API_KEY: record.key }, null, 2)}\n`) {
|
|
284
|
+
await rm(authPath);
|
|
285
|
+
log(`removed ${authPath} (the API-key login codex-app wrote)`);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
log(`${c("yellow", "left auth.json alone:")} it changed since codex-app wrote it (now ${kind}); remove or replace it yourself if that is not what you want.`);
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
await revokeKey(record.endpointId, record.keyId);
|
|
292
|
+
log(`revoked endpoint key …${record.keyHint}`);
|
|
293
|
+
}
|
|
294
|
+
catch (err) {
|
|
295
|
+
log(`${c("yellow", "could not revoke")} key …${record.keyHint} (${err instanceof Error ? err.message : String(err)}); revoke it from the developer console if it is still live`);
|
|
296
|
+
}
|
|
297
|
+
await updateStoredAuth({ codexApp: undefined });
|
|
298
|
+
log("codex-app wiring removed. Restart the Codex app (and any codex CLI session) to pick up the restored login.");
|
|
299
|
+
}
|
|
300
|
+
export async function runCodexApp(options) {
|
|
301
|
+
if (options.unset)
|
|
302
|
+
return unsetCodexApp();
|
|
303
|
+
const home = codexHome();
|
|
304
|
+
const configPath = path.join(home, "config.toml");
|
|
305
|
+
const authPath = path.join(home, "auth.json");
|
|
306
|
+
const authBackupPath = `${authPath}.pre-ditto`;
|
|
307
|
+
const configBackupPath = `${configPath}.pre-ditto`;
|
|
308
|
+
const selected = options.dryRun ? undefined : await ensureLogin();
|
|
309
|
+
const { endpoint, catalog } = await resolveEndpointFor(options, selected);
|
|
310
|
+
if (!options.dryRun)
|
|
311
|
+
await assertEndpointActive(endpoint);
|
|
312
|
+
const baseUrl = catalog.baseUrl;
|
|
313
|
+
const budget = parseBudget(options.budget);
|
|
314
|
+
const expiresIn = parseExpiry(options.expires);
|
|
315
|
+
const stored = await readStoredAuth();
|
|
316
|
+
const record = stored?.codexApp;
|
|
317
|
+
const configRaw = await readMaybe(configPath);
|
|
318
|
+
if (configRaw !== undefined) {
|
|
319
|
+
try {
|
|
320
|
+
parseToml(configRaw);
|
|
321
|
+
}
|
|
322
|
+
catch (err) {
|
|
323
|
+
throw new Error(`${configPath} does not parse as TOML (${err instanceof Error ? err.message : String(err)}); fix it before wiring the app`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
const authRaw = await readMaybe(authPath);
|
|
327
|
+
const authKind = classifyAuthJson(authRaw);
|
|
328
|
+
const pinningModel = options.model !== undefined;
|
|
329
|
+
const previousBaseUrl = previousValue(configRaw, "openai_base_url", record?.baseUrl, record?.previousBaseUrl);
|
|
330
|
+
const previousModel = pinningModel ? previousValue(configRaw, "model", record?.model, record?.previousModel) : undefined;
|
|
331
|
+
const previousForcedLogin = previousValue(configRaw, "forced_login_method", record?.forcedLogin ?? "api", record?.previousForcedLogin ?? null);
|
|
332
|
+
let newConfig = upsertTopLevelString(configRaw, "openai_base_url", baseUrl, CODEX_APP_MARKER);
|
|
333
|
+
// Force the API-key path: without this, a ChatGPT OAuth login (which can
|
|
334
|
+
// live outside auth.json, in the OS credential store) silently takes
|
|
335
|
+
// precedence and the app sends its OpenAI OAuth token to the Ditto
|
|
336
|
+
// gateway, which 401s it — the app breaks for its own OAuth usage.
|
|
337
|
+
newConfig = upsertTopLevelString(newConfig, "forced_login_method", "api");
|
|
338
|
+
if (pinningModel)
|
|
339
|
+
newConfig = upsertTopLevelString(newConfig, "model", options.model);
|
|
340
|
+
try {
|
|
341
|
+
const parsed = parseToml(newConfig);
|
|
342
|
+
if (parsed.openai_base_url !== baseUrl || parsed.forced_login_method !== "api" || (pinningModel && parsed.model !== options.model)) {
|
|
343
|
+
throw new Error("the edited file does not carry the new values");
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
throw new Error(`refusing to write ${configPath}: the edit does not parse back cleanly (${err instanceof Error ? err.message : String(err)})`);
|
|
348
|
+
}
|
|
349
|
+
if (authKind !== "absent" && !options.dryRun && !options.yes) {
|
|
350
|
+
if (!interactive()) {
|
|
351
|
+
throw new Error(`refusing to replace the existing ${authKind === "chatgpt" ? "ChatGPT-plan" : authKind === "api-key" ? "API-key" : "existing"} login in ${authPath} without confirmation. Re-run with --yes.`);
|
|
352
|
+
}
|
|
353
|
+
const what = authKind === "chatgpt" ? "your ChatGPT-plan login" : authKind === "api-key" ? "an existing API-key login" : "an unrecognized login";
|
|
354
|
+
const ok = await confirmYes(`Replace ${what} in ${authPath} (a backup is kept, --unset restores it)?`);
|
|
355
|
+
if (!ok)
|
|
356
|
+
throw new Error("aborted; nothing was written. (--yes skips this prompt.)");
|
|
357
|
+
}
|
|
358
|
+
if (options.dryRun) {
|
|
359
|
+
process.stdout.write(`${JSON.stringify({
|
|
360
|
+
endpoint: { id: endpoint.id, slug: endpoint.slug },
|
|
361
|
+
baseUrl,
|
|
362
|
+
codexHome: home,
|
|
363
|
+
write: {
|
|
364
|
+
[configPath]: { openai_base_url: baseUrl, forced_login_method: "api", ...(pinningModel ? { model: options.model } : {}) },
|
|
365
|
+
[authPath]: authKind === "absent" ? "{ OPENAI_API_KEY: <endpoint key> }" : `(replace the existing ${authKind === "chatgpt" ? "ChatGPT" : "API-key"} login; backup kept)`,
|
|
366
|
+
},
|
|
367
|
+
enableModelPicker: options.models !== false,
|
|
368
|
+
key: { name: options.name?.trim() || `cli:codex-app:${os.hostname()}`, expiresIn, spendLimitTokens: budget ?? null },
|
|
369
|
+
}, null, 2)}\n`);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const keyName = options.name?.trim() || `cli:codex-app:${os.hostname()}`;
|
|
373
|
+
const key = await createKey(endpoint.id, {
|
|
374
|
+
name: keyName,
|
|
375
|
+
expiresIn,
|
|
376
|
+
...(budget !== undefined ? { spendLimitTokens: budget, spendPeriod: "never" } : {}),
|
|
377
|
+
});
|
|
378
|
+
if (!key.key)
|
|
379
|
+
throw new Error("key creation succeeded but no plaintext key was returned");
|
|
380
|
+
await mkdir(home, { recursive: true, mode: 0o700 });
|
|
381
|
+
// Back the login up only when it is not codex-app's own: a re-run must not
|
|
382
|
+
// slide our previous key into the .pre-ditto slot, or --unset would later
|
|
383
|
+
// "restore" the codex-app login instead of removing it.
|
|
384
|
+
const authIsOurs = record !== undefined && authKind === "api-key" && authRaw === `${JSON.stringify({ OPENAI_API_KEY: record.key }, null, 2)}\n`;
|
|
385
|
+
const authBackupKept = authKind !== "absent" && !authIsOurs ? await backupOnce(authPath, authBackupPath) : false;
|
|
386
|
+
const configBackupKept = configRaw !== undefined ? await backupOnce(configPath, configBackupPath) : false;
|
|
387
|
+
await writeFile(configPath, newConfig, { mode: 0o600 });
|
|
388
|
+
await writeFile(authPath, `${JSON.stringify({ OPENAI_API_KEY: key.key }, null, 2)}\n`, { mode: 0o600 });
|
|
389
|
+
await chmod(authPath, 0o600);
|
|
390
|
+
await chmod(configPath, 0o600);
|
|
391
|
+
if (authBackupKept)
|
|
392
|
+
log(`previous login backed up to ${c("bold", authBackupPath)}`);
|
|
393
|
+
if (configBackupKept)
|
|
394
|
+
log(`previous config backed up to ${c("bold", configBackupPath)}`);
|
|
395
|
+
// The app's model picker lists the endpoint's models only when the
|
|
396
|
+
// endpoint says so; without it the app shows the OpenAI catalog and GLM
|
|
397
|
+
// Flash is nowhere in it.
|
|
398
|
+
let pickerEnabled = false;
|
|
399
|
+
if (options.models !== false) {
|
|
400
|
+
const current = endpoint.providerOptions;
|
|
401
|
+
if (current?.codex_models !== true) {
|
|
402
|
+
try {
|
|
403
|
+
await updateEndpoint(endpoint.id, { providerOptions: { ...(current ?? {}), codex_models: true } });
|
|
404
|
+
pickerEnabled = true;
|
|
405
|
+
}
|
|
406
|
+
catch (err) {
|
|
407
|
+
log(`${c("yellow", "could not enable the model picker on this endpoint")} (${err instanceof Error ? err.message : String(err)}); enable it with \`heyditto endpoints set ${endpoint.slug} --codex-models on\``);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
// Rotate: the previous run's key has no reason to outlive its replacement.
|
|
412
|
+
if (record?.keyId) {
|
|
413
|
+
try {
|
|
414
|
+
await revokeKey(record.endpointId, record.keyId);
|
|
415
|
+
log(`revoked the previous codex-app key …${record.keyHint}`);
|
|
416
|
+
}
|
|
417
|
+
catch {
|
|
418
|
+
log(`${c("yellow", "could not revoke the previous codex-app key")} …${record.keyHint}; it expires on its own`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
await updateStoredAuth({
|
|
422
|
+
codexApp: {
|
|
423
|
+
endpointId: endpoint.id,
|
|
424
|
+
endpointSlug: endpoint.slug,
|
|
425
|
+
keyId: key.id,
|
|
426
|
+
keyHint: key.keyHint,
|
|
427
|
+
key: key.key,
|
|
428
|
+
baseUrl,
|
|
429
|
+
forcedLogin: "api",
|
|
430
|
+
...(pinningModel ? { model: options.model, previousModel: previousModel ?? null } : {}),
|
|
431
|
+
previousBaseUrl,
|
|
432
|
+
previousForcedLogin,
|
|
433
|
+
wiredAt: new Date().toISOString(),
|
|
434
|
+
},
|
|
435
|
+
});
|
|
436
|
+
log(`endpoint=${c(["bold", "cyan"], endpoint.slug)} key=…${key.keyHint} expires=${expiresIn} codexHome=${home}`);
|
|
437
|
+
log(`wrote ${c("bold", "openai_base_url")} into ${configPath}`);
|
|
438
|
+
log(`wrote ${c("bold", 'forced_login_method = "api"')} so the app uses this key instead of a ChatGPT OAuth login (which would 401 against the gateway)`);
|
|
439
|
+
log(`wrote the endpoint key to ${authPath}${authBackupKept ? ` (backup: ${authBackupPath})` : ""}`);
|
|
440
|
+
if (pickerEnabled)
|
|
441
|
+
log(`enabled the model picker on ${endpoint.slug} — the app's /model lists its models`);
|
|
442
|
+
log(`traces: ${c(["underline", "cyan"], endpointURL(endpoint.id))}`);
|
|
443
|
+
log(`(re)start the Codex app. On the sign-in screen pick ${c("bold", '"Sign in with an API key"')}; the key written above is the one it asks for.${options.showKey ? "" : " Print it with --show-key."}`);
|
|
444
|
+
if (options.showKey)
|
|
445
|
+
log(`endpoint key: ${c("bold", key.key)}`);
|
|
446
|
+
log(`${c("yellow", "note:")} ~/.codex is shared with the codex CLI — bare \`codex\` runs now route through Ditto too. \`heyditto codex\` is unaffected.`);
|
|
447
|
+
log(`undo with: ${c("bold", "heyditto codex-app --unset")}`);
|
|
448
|
+
}
|
|
449
|
+
/** Registers `codex-app` on the program (which must have enablePositionalOptions()). */
|
|
450
|
+
export function registerCodexAppCommand(program, addExamples) {
|
|
451
|
+
addExamples(program
|
|
452
|
+
.command("codex-app")
|
|
453
|
+
.description('wire the Codex desktop app (ChatGPT.app) to a Ditto inference endpoint, so its models work behind the app\'s "Sign in with an API key"')
|
|
454
|
+
.summary("wire the Codex desktop app to a Ditto endpoint")
|
|
455
|
+
.option("-e, --endpoint <slug>", "inference endpoint slug or id (default: saved default, or a picker)")
|
|
456
|
+
.option("--budget <tokens>", "spend cap for the app's key, in Ditto tokens")
|
|
457
|
+
.addOption(new Option("--expires <duration>", "server-side expiry for the app's key (replaced on the next run, revoked by --unset)")
|
|
458
|
+
.choices([...KEY_EXPIRIES])
|
|
459
|
+
.default(DEFAULT_LAUNCH_EXPIRY))
|
|
460
|
+
.option("--model <id>", "pin the app's model (writes `model` in config.toml; otherwise pick models in the app)")
|
|
461
|
+
.option("--no-models", "do not enable the endpoint's model picker (codex_models)")
|
|
462
|
+
.option("--name <label>", "key name shown in the Ditto app (default: cli:codex-app:<hostname>)")
|
|
463
|
+
.option("--show-key", "print the endpoint key after wiring (for pasting into the app's sign-in screen)")
|
|
464
|
+
.option("--unset", "restore the previous config.toml/auth.json and revoke the key")
|
|
465
|
+
.option("-y, --yes", "replace an existing Codex login without asking")
|
|
466
|
+
.option("--dry-run", "print what would be written without touching anything")
|
|
467
|
+
.action(async (options) => {
|
|
468
|
+
await runCodexApp(options);
|
|
469
|
+
}), ` heyditto codex-app sign in, pick an endpoint, wire the app
|
|
470
|
+
heyditto codex-app --endpoint my-endpoint --budget 500000
|
|
471
|
+
heyditto codex-app --model glm-5.3-flash pin the app's model
|
|
472
|
+
heyditto codex-app --dry-run show what would be written
|
|
473
|
+
heyditto codex-app --unset restore the previous wiring and revoke the key`);
|
|
474
|
+
}
|
|
475
|
+
//# sourceMappingURL=codexapp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexapp.js","sourceRoot":"","sources":["../../src/agents/codexapp.ts"],"names":[],"mappings":"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"}
|