@ai21/gateway 1.3.1 → 1.5.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 +52 -17
- package/dist/agents/claude-code/desktop.d.ts +81 -0
- package/dist/agents/claude-code/desktop.js +615 -0
- package/dist/agents/claude-code/desktop.js.map +1 -0
- package/dist/agents/claude-code/desktopWindows.d.ts +10 -0
- package/dist/agents/claude-code/desktopWindows.js +151 -0
- package/dist/agents/claude-code/desktopWindows.js.map +1 -0
- package/dist/agents/claude-code/index.d.ts +7 -0
- package/dist/agents/claude-code/index.js +114 -0
- package/dist/agents/claude-code/index.js.map +1 -0
- package/dist/agents/claude-code/verify.d.ts +8 -50
- package/dist/agents/claude-code/verify.js +22 -9
- package/dist/agents/claude-code/verify.js.map +1 -1
- package/dist/agents/codex/config.d.ts +20 -0
- package/dist/agents/codex/config.js +347 -0
- package/dist/agents/codex/config.js.map +1 -0
- package/dist/agents/codex/index.d.ts +2 -0
- package/dist/agents/codex/index.js +79 -0
- package/dist/agents/codex/index.js.map +1 -0
- package/dist/agents/codex/snippets.d.ts +23 -0
- package/dist/agents/codex/snippets.js +39 -0
- package/dist/agents/codex/snippets.js.map +1 -0
- package/dist/agents/codex/status.d.ts +8 -0
- package/dist/agents/codex/status.js +36 -0
- package/dist/agents/codex/status.js.map +1 -0
- package/dist/agents/codex/toml.d.ts +57 -0
- package/dist/agents/codex/toml.js +196 -0
- package/dist/agents/codex/toml.js.map +1 -0
- package/dist/agents/codex/verify.d.ts +2 -0
- package/dist/agents/codex/verify.js +43 -0
- package/dist/agents/codex/verify.js.map +1 -0
- package/dist/agents/registry.d.ts +10 -0
- package/dist/agents/registry.js +14 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/types.d.ts +45 -0
- package/dist/agents/types.js.map +1 -1
- package/dist/args.d.ts +2 -3
- package/dist/args.js +7 -9
- package/dist/args.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +19 -12
- package/dist/cli.js.map +1 -1
- package/dist/fs/safeFile.d.ts +1 -0
- package/dist/fs/safeFile.js.map +1 -1
- package/dist/fs/snapshot.d.ts +1 -1
- package/dist/fs/snapshot.js +1 -1
- package/dist/login/browser.js +2 -4
- package/dist/login/browser.js.map +1 -1
- package/dist/precheck.d.ts +4 -1
- package/dist/precheck.js +12 -9
- package/dist/precheck.js.map +1 -1
- package/dist/process.d.ts +2 -0
- package/dist/process.js +6 -4
- package/dist/process.js.map +1 -1
- package/dist/report.d.ts +16 -19
- package/dist/report.js +36 -62
- package/dist/report.js.map +1 -1
- package/dist/result.d.ts +7 -5
- package/dist/result.js +7 -5
- package/dist/result.js.map +1 -1
- package/dist/router.d.ts +7 -2
- package/dist/router.js +171 -114
- package/dist/router.js.map +1 -1
- package/dist/status.js +11 -3
- package/dist/status.js.map +1 -1
- package/dist/telemetry/events.d.ts +3 -2
- package/dist/telemetry/events.js +0 -6
- package/dist/telemetry/events.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Writing and reverting our part of `~/.codex/config.toml`.
|
|
3
|
+
*
|
|
4
|
+
* Same constraint as Claude Code's writer: this edits a file the developer owns. Every
|
|
5
|
+
* path leaves it byte-identical or replaces it atomically, with a `.bak` of the last
|
|
6
|
+
* state that was not ours, and no refusal touches it.
|
|
7
|
+
*
|
|
8
|
+
* What we own: the root `model_provider` line, and the `[model_providers.ai21]` and
|
|
9
|
+
* `[model_providers.ai21.http_headers]` tables, wrapped in marker comments when we add
|
|
10
|
+
* them. Whether a file is *ours* is judged by an `x-ai21-client` header naming this
|
|
11
|
+
* tool — a hand-pasted block from the dashboard has an `x-ai21-key` too, and must stay
|
|
12
|
+
* the developer's until they say otherwise with `--yes`.
|
|
13
|
+
*/
|
|
14
|
+
import { chmodSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readlinkSync, realpathSync, rmSync, } from "node:fs";
|
|
15
|
+
import { dirname, join, resolve } from "node:path";
|
|
16
|
+
import { atomicWrite, backupPathFor, describeFsError } from "../../fs/safeFile.js";
|
|
17
|
+
import { ROOT_LINE, codexHeaders, codexTables } from "./snippets.js";
|
|
18
|
+
import { HEADERS_TABLE, PROVIDER_ID, PROVIDER_TABLE, entries, joinLines, newlineOf, removeRange, scan, stringValue, } from "./toml.js";
|
|
19
|
+
/** What a conflict shows instead of an AI21 key. */
|
|
20
|
+
export const REDACTED = "****";
|
|
21
|
+
export const MARKER_BEGIN = "# >>> AI21 Gateway (managed by ai21-gateway; `ai21-gateway uninstall --client codex` removes it)";
|
|
22
|
+
export const MARKER_END = "# <<< AI21 Gateway";
|
|
23
|
+
/** `CODEX_HOME` wins, as it does for Codex; a relative one is resolved against the cwd, as Codex does. */
|
|
24
|
+
export function codexHome(env) {
|
|
25
|
+
const override = env.processEnv.CODEX_HOME;
|
|
26
|
+
return override !== undefined && override !== "" ? resolve(env.cwd, override) : join(env.home, ".codex");
|
|
27
|
+
}
|
|
28
|
+
export function resolveCodexPaths(dir) {
|
|
29
|
+
const settings = join(dir, "config.toml");
|
|
30
|
+
return { settings, backup: `${settings}.bak` };
|
|
31
|
+
}
|
|
32
|
+
/** Our client tag marks a block this tool wrote; nothing else does. */
|
|
33
|
+
function isOurs(scanned) {
|
|
34
|
+
const client = entries(scanned, scanned.headers).get("x-ai21-client");
|
|
35
|
+
return client !== undefined && /^"ai21-gateway-cli\//.test(client);
|
|
36
|
+
}
|
|
37
|
+
/** The agent id our block names, for the uninstall guard. */
|
|
38
|
+
export function storedAgentId(scanned) {
|
|
39
|
+
const raw = entries(scanned, scanned.headers).get("x-agent-id");
|
|
40
|
+
return raw === undefined ? undefined : stringValue(`x = ${raw}`);
|
|
41
|
+
}
|
|
42
|
+
/** The value a root `model_provider` line assigns, or undefined without one. */
|
|
43
|
+
function rootProvider(scanned) {
|
|
44
|
+
if (scanned.rootModelProvider === undefined)
|
|
45
|
+
return undefined;
|
|
46
|
+
return stringValue(scanned.lines[scanned.rootModelProvider].text);
|
|
47
|
+
}
|
|
48
|
+
/** Resolves a symlink one level, so a write goes through the link rather than replacing it. */
|
|
49
|
+
function followLink(path) {
|
|
50
|
+
try {
|
|
51
|
+
if (lstatSync(path, { throwIfNoEntry: false })?.isSymbolicLink() === true) {
|
|
52
|
+
return resolve(dirname(path), readlinkSync(path));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return path;
|
|
57
|
+
}
|
|
58
|
+
return path;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The file with our part put in: the root line replaced in place or inserted above the
|
|
62
|
+
* first table, and our tables replaced in place or appended in a marked block. Every
|
|
63
|
+
* position comes from the scan; nothing is found again by matching text, since another
|
|
64
|
+
* provider's table can hold the same lines as ours.
|
|
65
|
+
*/
|
|
66
|
+
function withOurs(scanned, inputs) {
|
|
67
|
+
const nl = newlineOf(scanned.lines);
|
|
68
|
+
const asLines = (texts) => texts.map((text) => ({ text, eol: nl }));
|
|
69
|
+
const tables = codexTables(inputs);
|
|
70
|
+
const split = tables.indexOf(`[${HEADERS_TABLE}]`);
|
|
71
|
+
const providerLines = tables.slice(0, split);
|
|
72
|
+
const headerLines = tables.slice(split);
|
|
73
|
+
/** A region's last line that is a key, so comments and blanks after it stay put. */
|
|
74
|
+
const keysEnd = (region) => {
|
|
75
|
+
let end = region.end;
|
|
76
|
+
while (end > region.start + 1 && /^\s*(#.*)?$/.test(scanned.lines[end - 1].text))
|
|
77
|
+
end -= 1;
|
|
78
|
+
return end;
|
|
79
|
+
};
|
|
80
|
+
// Edits as [start, end, replacement], applied bottom-up so earlier indices stay valid.
|
|
81
|
+
const edits = [];
|
|
82
|
+
const { provider, headers } = scanned;
|
|
83
|
+
if (provider === undefined && headers === undefined) {
|
|
84
|
+
const lines = scanned.lines;
|
|
85
|
+
const last = lines.at(-1);
|
|
86
|
+
const fix = last !== undefined && last.eol === "" ? [{ ...last, eol: nl }] : [];
|
|
87
|
+
const gap = lines.length > 0 && lines.at(-1).text.trim() !== "" ? asLines([""]) : [];
|
|
88
|
+
const at = lines.length - fix.length;
|
|
89
|
+
edits.push([at, lines.length, [...fix, ...gap, ...asLines([MARKER_BEGIN, ...tables, MARKER_END])]]);
|
|
90
|
+
}
|
|
91
|
+
else if (provider !== undefined && headers !== undefined) {
|
|
92
|
+
edits.push([provider.start, keysEnd(provider), asLines(providerLines)]);
|
|
93
|
+
edits.push([headers.start, keysEnd(headers), asLines(headerLines)]);
|
|
94
|
+
}
|
|
95
|
+
else if (provider !== undefined) {
|
|
96
|
+
// Headers go straight after the provider table's keys.
|
|
97
|
+
edits.push([provider.start, keysEnd(provider), asLines([...providerLines, ...headerLines])]);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// Provider keys go straight before the headers table.
|
|
101
|
+
edits.push([headers.start, keysEnd(headers), asLines([...providerLines, ...headerLines])]);
|
|
102
|
+
}
|
|
103
|
+
let lines = [...scanned.lines];
|
|
104
|
+
for (const [start, end, replacement] of edits.sort((x, y) => y[0] - x[0])) {
|
|
105
|
+
lines = [...lines.slice(0, start), ...replacement, ...lines.slice(end)];
|
|
106
|
+
}
|
|
107
|
+
// Root keys sit before the first table, and every edit above is at or after it.
|
|
108
|
+
if (scanned.rootModelProvider !== undefined) {
|
|
109
|
+
lines[scanned.rootModelProvider] = { text: ROOT_LINE, eol: lines[scanned.rootModelProvider].eol };
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
lines = [...asLines([ROOT_LINE]), ...lines];
|
|
113
|
+
}
|
|
114
|
+
const joined = joinLines(lines);
|
|
115
|
+
return joined.endsWith(nl) ? joined : joined + nl;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* A structural re-read of what we are about to write: exactly one of each of our tables,
|
|
119
|
+
* the root line selecting ours, and nothing the scanner would refuse. Not a TOML parser —
|
|
120
|
+
* a line-level check that our own edit did not break the shape we rely on.
|
|
121
|
+
*/
|
|
122
|
+
function checkWritten(text) {
|
|
123
|
+
const again = scan(text);
|
|
124
|
+
if (again.unsupported !== undefined)
|
|
125
|
+
return "the edited file would not keep a valid shape";
|
|
126
|
+
if (again.provider === undefined || again.headers === undefined)
|
|
127
|
+
return "the edited file lost a provider table";
|
|
128
|
+
if (rootProvider(again) !== PROVIDER_ID)
|
|
129
|
+
return "the edited file would not select the AI21 provider";
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
/** Every value we would set, compared with what the file holds now. */
|
|
133
|
+
function differences(scanned, inputs) {
|
|
134
|
+
const changed = [];
|
|
135
|
+
const conflicts = [];
|
|
136
|
+
const want = (key, current, desired, conflicting) => {
|
|
137
|
+
if (current === desired)
|
|
138
|
+
return;
|
|
139
|
+
changed.push(key);
|
|
140
|
+
// The key is masked here, where the conflict is made, so no later step can print it.
|
|
141
|
+
const secret = key === `${HEADERS_TABLE}.x-ai21-key`;
|
|
142
|
+
if (current !== undefined && conflicting) {
|
|
143
|
+
conflicts.push({ key, current: secret ? REDACTED : current, desired: secret ? REDACTED : desired });
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const provider = entries(scanned, scanned.provider);
|
|
147
|
+
const headers = entries(scanned, scanned.headers);
|
|
148
|
+
// A root model_provider naming another provider is the developer's choice; ours replaces it.
|
|
149
|
+
want("model_provider", rootProvider(scanned), PROVIDER_ID, true);
|
|
150
|
+
// Only the provider table's own lines: they end where the headers table begins.
|
|
151
|
+
const tables = codexTables(inputs);
|
|
152
|
+
const providerKeyLines = tables.slice(1, tables.indexOf(`[${HEADERS_TABLE}]`));
|
|
153
|
+
for (const line of providerKeyLines) {
|
|
154
|
+
const [key] = line.split(" = ");
|
|
155
|
+
want(`${PROVIDER_TABLE}.${key}`, provider.get(key), line.slice(line.indexOf("=") + 1).trim(), true);
|
|
156
|
+
}
|
|
157
|
+
for (const [key, value] of codexHeaders(inputs)) {
|
|
158
|
+
const current = headers.get(key);
|
|
159
|
+
want(`${HEADERS_TABLE}.${key}`, current === undefined ? undefined : stringValue(`x = ${current}`), value, true);
|
|
160
|
+
}
|
|
161
|
+
// Keys in our tables that we do not write, e.g. a stale x-ai21-user-id: they go too.
|
|
162
|
+
for (const key of [...provider.keys()].filter((k) => !providerKeyLines.some((l) => l.startsWith(`${k} =`)))) {
|
|
163
|
+
changed.push(`${PROVIDER_TABLE}.${key}`);
|
|
164
|
+
conflicts.push({ key: `${PROVIDER_TABLE}.${key}`, current: provider.get(key), desired: "(removed)" });
|
|
165
|
+
}
|
|
166
|
+
for (const key of [...headers.keys()].filter((k) => !codexHeaders(inputs).some(([h]) => h === k))) {
|
|
167
|
+
changed.push(`${HEADERS_TABLE}.${key}`);
|
|
168
|
+
conflicts.push({ key: `${HEADERS_TABLE}.${key}`, current: headers.get(key), desired: "(removed)" });
|
|
169
|
+
}
|
|
170
|
+
return { changed, conflicts };
|
|
171
|
+
}
|
|
172
|
+
function load(path) {
|
|
173
|
+
let realPath;
|
|
174
|
+
let raw;
|
|
175
|
+
try {
|
|
176
|
+
realPath = realpathSync(path);
|
|
177
|
+
raw = readFileSync(realPath, "utf8");
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
return { problem: { kind: "failed", reason: describeFsError(err) } };
|
|
181
|
+
}
|
|
182
|
+
const scanned = scan(raw);
|
|
183
|
+
if (scanned.unsupported !== undefined)
|
|
184
|
+
return { problem: { kind: "malformed", reason: scanned.unsupported } };
|
|
185
|
+
return { loaded: { realPath, raw, scanned } };
|
|
186
|
+
}
|
|
187
|
+
export function writeCodexConfig(paths, inputs, options) {
|
|
188
|
+
const { settings: path } = paths;
|
|
189
|
+
const target = followLink(path);
|
|
190
|
+
if (!existsSync(path)) {
|
|
191
|
+
try {
|
|
192
|
+
mkdirSync(dirname(target), { recursive: true, mode: 0o700 });
|
|
193
|
+
// A new file has no earlier state, so a backup left by a past install must not be restored into it.
|
|
194
|
+
rmSync(backupPathFor(paths, target), { force: true });
|
|
195
|
+
atomicWrite(target, withOurs(scan(""), inputs));
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
return { kind: "failed", path, reason: describeFsError(err) };
|
|
199
|
+
}
|
|
200
|
+
return { kind: "created", path };
|
|
201
|
+
}
|
|
202
|
+
const result = load(path);
|
|
203
|
+
if ("problem" in result)
|
|
204
|
+
return { ...result.problem, path };
|
|
205
|
+
const { realPath, scanned } = result.loaded;
|
|
206
|
+
const { changed, conflicts } = differences(scanned, inputs);
|
|
207
|
+
// Same rule as Claude Code: any value that would change needs --yes, ours or not.
|
|
208
|
+
if (conflicts.length > 0 && !options.force)
|
|
209
|
+
return { kind: "conflict", path, conflicts };
|
|
210
|
+
if (changed.length === 0)
|
|
211
|
+
return { kind: "unchanged", path };
|
|
212
|
+
const next = withOurs(scanned, inputs);
|
|
213
|
+
const broken = checkWritten(next);
|
|
214
|
+
if (broken !== undefined)
|
|
215
|
+
return { kind: "malformed", path, reason: broken };
|
|
216
|
+
const backupPath = backupPathFor(paths, realPath);
|
|
217
|
+
try {
|
|
218
|
+
// The backup holds the last state that was not ours, so a re-run never buries it.
|
|
219
|
+
if (!isOurs(scanned)) {
|
|
220
|
+
copyFileSync(realPath, backupPath);
|
|
221
|
+
chmodSync(backupPath, 0o600);
|
|
222
|
+
}
|
|
223
|
+
atomicWrite(realPath, next);
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
return { kind: "failed", path, reason: describeFsError(err) };
|
|
227
|
+
}
|
|
228
|
+
return { kind: "updated", path, backup: backupPath, changed };
|
|
229
|
+
}
|
|
230
|
+
/** The file without our part: our tables removed, and the root line put back as it was before us. */
|
|
231
|
+
function withoutOurs(scanned, before) {
|
|
232
|
+
const removed = [];
|
|
233
|
+
const restored = [];
|
|
234
|
+
let lines = [...scanned.lines];
|
|
235
|
+
/* The backup holds the last state that was not ours. A table it has — a block the
|
|
236
|
+
* developer pasted by hand before `--yes` replaced it — goes back as it was, line for
|
|
237
|
+
* line; a table it lacks is one we added, so it goes. */
|
|
238
|
+
const previousLines = (name) => {
|
|
239
|
+
const region = before?.[name];
|
|
240
|
+
if (before === undefined || region === undefined)
|
|
241
|
+
return undefined;
|
|
242
|
+
let end = region.end;
|
|
243
|
+
while (end > region.start + 1 && /^\s*(#.*)?$/.test(before.lines[end - 1].text))
|
|
244
|
+
end -= 1;
|
|
245
|
+
return before.lines.slice(region.start, end);
|
|
246
|
+
};
|
|
247
|
+
const ours = ["provider", "headers"]
|
|
248
|
+
.filter((name) => scanned[name] !== undefined)
|
|
249
|
+
.sort((a, b) => scanned[b].start - scanned[a].start);
|
|
250
|
+
for (const name of ours) {
|
|
251
|
+
const region = scanned[name];
|
|
252
|
+
const table = name === "headers" ? HEADERS_TABLE : PROVIDER_TABLE;
|
|
253
|
+
const previous = previousLines(name);
|
|
254
|
+
let { start, end } = region;
|
|
255
|
+
while (end > start + 1 && /^\s*(#.*)?$/.test(lines[end - 1].text))
|
|
256
|
+
end -= 1;
|
|
257
|
+
if (previous !== undefined) {
|
|
258
|
+
lines = [...lines.slice(0, start), ...previous, ...lines.slice(end)];
|
|
259
|
+
restored.push(table);
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
// Take our marker lines with us when they sit right around the tables.
|
|
263
|
+
end = region.end;
|
|
264
|
+
while (end < lines.length && lines[end].text === MARKER_END)
|
|
265
|
+
end += 1;
|
|
266
|
+
while (start > 0 && lines[start - 1].text.startsWith(MARKER_BEGIN))
|
|
267
|
+
start -= 1;
|
|
268
|
+
lines = removeRange(lines, start, end);
|
|
269
|
+
removed.push(table);
|
|
270
|
+
}
|
|
271
|
+
// A marker left behind by a hand edit between them.
|
|
272
|
+
lines = lines.filter((l) => !l.text.startsWith(MARKER_BEGIN) && l.text !== MARKER_END);
|
|
273
|
+
if (scanned.rootModelProvider !== undefined) {
|
|
274
|
+
const previous = before === undefined ? undefined : before.rootModelProvider;
|
|
275
|
+
const index = scanned.rootModelProvider;
|
|
276
|
+
// Put back whatever the backup had, even our own id: a block pasted by hand needs its root line too.
|
|
277
|
+
if (previous !== undefined) {
|
|
278
|
+
lines[index] = { ...before.lines[previous], eol: lines[index].eol };
|
|
279
|
+
restored.push("model_provider");
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
lines = [...lines.slice(0, index), ...lines.slice(index + 1)];
|
|
283
|
+
removed.push("model_provider");
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
// Leading blank lines we left by removing the root line.
|
|
287
|
+
while (lines.length > 0 && lines[0].text.trim() === "" && (scanned.lines[0]?.text.trim() ?? "") !== "")
|
|
288
|
+
lines.shift();
|
|
289
|
+
return { text: joinLines(lines), removed, restored };
|
|
290
|
+
}
|
|
291
|
+
export function revertCodexConfig(paths, options) {
|
|
292
|
+
const { settings: path } = paths;
|
|
293
|
+
if (!existsSync(followLink(path)))
|
|
294
|
+
return { kind: "not-configured", path };
|
|
295
|
+
const result = load(path);
|
|
296
|
+
if ("problem" in result)
|
|
297
|
+
return { ...result.problem, path };
|
|
298
|
+
const { realPath, raw, scanned } = result.loaded;
|
|
299
|
+
if (!isOurs(scanned))
|
|
300
|
+
return { kind: "not-configured", path };
|
|
301
|
+
if (options.agentIdGuard !== undefined) {
|
|
302
|
+
const stored = storedAgentId(scanned);
|
|
303
|
+
if (stored !== options.agentIdGuard) {
|
|
304
|
+
return { kind: "agent-mismatch", path, expected: options.agentIdGuard, actual: stored ?? "none" };
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const backup = backupPathFor(paths, realPath);
|
|
308
|
+
let backupRaw;
|
|
309
|
+
let backupUnreadable = false;
|
|
310
|
+
if (existsSync(backup)) {
|
|
311
|
+
try {
|
|
312
|
+
backupRaw = readFileSync(backup, "utf8");
|
|
313
|
+
}
|
|
314
|
+
catch {
|
|
315
|
+
backupUnreadable = true;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (options.fromBackup) {
|
|
319
|
+
if (backupRaw === undefined)
|
|
320
|
+
return backupUnreadable
|
|
321
|
+
? { kind: "failed", path, reason: "the backup could not be read" }
|
|
322
|
+
: { kind: "no-backup", path, backup };
|
|
323
|
+
if (!options.force && withoutOurs(scanned, undefined).text !== withoutOurs(scan(backupRaw), undefined).text) {
|
|
324
|
+
return { kind: "drifted", path, backup };
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
// Byte for byte: "verbatim" includes the developer's formatting and comments.
|
|
328
|
+
copyFileSync(backup, realPath);
|
|
329
|
+
}
|
|
330
|
+
catch (err) {
|
|
331
|
+
return { kind: "failed", path, reason: describeFsError(err) };
|
|
332
|
+
}
|
|
333
|
+
return { kind: "restored", path, backup };
|
|
334
|
+
}
|
|
335
|
+
const before = backupRaw === undefined ? undefined : scan(backupRaw);
|
|
336
|
+
const { text, removed, restored } = withoutOurs(scanned, before);
|
|
337
|
+
if (text === raw)
|
|
338
|
+
return { kind: "not-configured", path };
|
|
339
|
+
try {
|
|
340
|
+
atomicWrite(realPath, text);
|
|
341
|
+
}
|
|
342
|
+
catch (err) {
|
|
343
|
+
return { kind: "failed", path, reason: describeFsError(err) };
|
|
344
|
+
}
|
|
345
|
+
return { kind: "reverted", path, removed, restored, backupUnreadable };
|
|
346
|
+
}
|
|
347
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/agents/codex/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,MAAM,GACP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAoB,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAErG,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EACL,aAAa,EAEb,WAAW,EACX,cAAc,EAEd,OAAO,EACP,SAAS,EACT,SAAS,EACT,WAAW,EACX,IAAI,EACJ,WAAW,GACZ,MAAM,WAAW,CAAC;AAEnB,oDAAoD;AACpD,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC;AAE/B,MAAM,CAAC,MAAM,YAAY,GACvB,kGAAkG,CAAC;AACrG,MAAM,CAAC,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAE/C,0GAA0G;AAC1G,MAAM,UAAU,SAAS,CAAC,GAIzB;IACC,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;IAC3C,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC3G,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,QAAQ,MAAM,EAAE,CAAC;AACjD,CAAC;AAED,uEAAuE;AACvE,SAAS,MAAM,CAAC,OAAa;IAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACtE,OAAO,MAAM,KAAK,SAAS,IAAI,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACrE,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,aAAa,CAAC,OAAa;IACzC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAChE,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;AACnE,CAAC;AAED,gFAAgF;AAChF,SAAS,YAAY,CAAC,OAAa;IACjC,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAE9D,OAAO,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAE,CAAC,IAAI,CAAC,CAAC;AACrE,CAAC;AAED,+FAA+F;AAC/F,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC;QACH,IAAI,SAAS,CAAC,IAAI,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,EAAE,cAAc,EAAE,KAAK,IAAI,EAAE,CAAC;YAC1E,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,QAAQ,CAAC,OAAa,EAAE,MAAqB;IACpD,MAAM,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,CAAC,KAAwB,EAAU,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC/F,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC;IACnD,MAAM,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAExC,oFAAoF;IACpF,MAAM,OAAO,GAAG,CAAC,MAAsC,EAAU,EAAE;QACjE,IAAI,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACrB,OAAO,GAAG,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC;YAAE,GAAG,IAAI,CAAC,CAAC;QAC5F,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IAEF,uFAAuF;IACvF,MAAM,KAAK,GAA+B,EAAE,CAAC;IAC7C,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACtC,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1B,MAAM,GAAG,GAAW,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,CAAC,YAAY,EAAE,GAAG,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;QACxE,KAAK,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;SAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAClC,uDAAuD;QACvD,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC;SAAM,CAAC;QACN,sDAAsD;QACtD,KAAK,CAAC,IAAI,CAAC,CAAC,OAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,OAAQ,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,aAAa,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1E,CAAC;IAED,gFAAgF;IAChF,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC5C,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAE,CAAC,GAAG,EAAE,CAAC;IACrG,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC;AACpD,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IACzB,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,8CAA8C,CAAC;IAE3F,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,uCAAuC,CAAC;IAEhH,IAAI,YAAY,CAAC,KAAK,CAAC,KAAK,WAAW;QAAE,OAAO,oDAAoD,CAAC;IAErG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uEAAuE;AACvE,SAAS,WAAW,CAAC,OAAa,EAAE,MAAqB;IACvD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,SAAS,GAAe,EAAE,CAAC;IACjC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE,OAA2B,EAAE,OAAe,EAAE,WAAoB,EAAQ,EAAE;QACrG,IAAI,OAAO,KAAK,OAAO;YAAE,OAAO;QAEhC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,qFAAqF;QACrF,MAAM,MAAM,GAAG,GAAG,KAAK,GAAG,aAAa,aAAa,CAAC;QACrD,IAAI,OAAO,KAAK,SAAS,IAAI,WAAW,EAAE,CAAC;YACzC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACtG,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,6FAA6F;IAC7F,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAC,OAAO,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;IACjE,gFAAgF;IAChF,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;IAC/E,KAAK,MAAM,IAAI,IAAI,gBAAgB,EAAE,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChC,IAAI,CAAC,GAAG,cAAc,IAAI,GAAG,EAAE,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC;IACvG,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,aAAa,IAAI,GAAG,EAAE,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IAClH,CAAC;IACD,qFAAqF;IACrF,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5G,OAAO,CAAC,IAAI,CAAC,GAAG,cAAc,IAAI,GAAG,EAAE,CAAC,CAAC;QACzC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,cAAc,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IACzG,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAClG,OAAO,CAAC,IAAI,CAAC,GAAG,aAAa,IAAI,GAAG,EAAE,CAAC,CAAC;QACxC,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,aAAa,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;IACvG,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAQD,SAAS,IAAI,CAAC,IAAY;IACxB,IAAI,QAAgB,CAAC;IACrB,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAC9B,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;IAE9G,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,KAAkB,EAClB,MAAqB,EACrB,OAAoC;IAEpC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACjC,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAEhC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC;YACH,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;YAC7D,oGAAoG;YACpG,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QAChE,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IACnC,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,SAAS,IAAI,MAAM;QAAE,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IAE5D,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;IAE5C,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5D,kFAAkF;IAClF,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAEzF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;IAE7D,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAE7E,MAAM,UAAU,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClD,IAAI,CAAC;QACH,kFAAkF;QAClF,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YACrB,YAAY,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YACnC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;IAChE,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC;AAChE,CAAC;AAED,qGAAqG;AACrG,SAAS,WAAW,CAAC,OAAa,EAAE,MAAwB;IAC1D,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAE/B;;6DAEyD;IACzD,MAAM,aAAa,GAAG,CAAC,IAA4B,EAAsB,EAAE;QACzE,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAEnE,IAAI,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACrB,OAAO,GAAG,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC;YAAE,GAAG,IAAI,CAAC,CAAC;QAE3F,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC,CAAC;IAEF,MAAM,IAAI,GAAI,CAAC,UAAU,EAAE,SAAS,CAAW;SAC5C,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;SAC7C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,KAAK,CAAC,CAAC;IACzD,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,cAAc,CAAC;QAClE,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;QAC5B,OAAO,GAAG,GAAG,KAAK,GAAG,CAAC,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC;YAAE,GAAG,IAAI,CAAC,CAAC;QAC7E,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,SAAS;QACX,CAAC;QAED,uEAAuE;QACvE,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;QACjB,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,GAAG,CAAE,CAAC,IAAI,KAAK,UAAU;YAAE,GAAG,IAAI,CAAC,CAAC;QACvE,OAAO,KAAK,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;QAChF,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,oDAAoD;IACpD,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IAEvF,IAAI,OAAO,CAAC,iBAAiB,KAAK,SAAS,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;QAC7E,MAAM,KAAK,GAAG,OAAO,CAAC,iBAAiB,CAAC;QACxC,qGAAqG;QACrG,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,MAAO,CAAC,KAAK,CAAC,QAAQ,CAAE,EAAE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAE,CAAC,GAAG,EAAE,CAAC;YACvE,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE;QACrG,KAAK,CAAC,KAAK,EAAE,CAAC;IAEhB,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAkB,EAAE,OAAsB;IAC1E,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACjC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;IAE3E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,IAAI,SAAS,IAAI,MAAM;QAAE,OAAO,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;IAE5D,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;IAEjD,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;IAE9D,IAAI,OAAO,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,MAAM,KAAK,OAAO,CAAC,YAAY,EAAE,CAAC;YACpC,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM,EAAE,CAAC;QACpG,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAC9C,IAAI,SAA6B,CAAC;IAClC,IAAI,gBAAgB,GAAG,KAAK,CAAC;IAC7B,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,IAAI,CAAC;YACH,SAAS,GAAG,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,gBAAgB,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,IAAI,SAAS,KAAK,SAAS;YACzB,OAAO,gBAAgB;gBACrB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,8BAA8B,EAAE;gBAClE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAE1C,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,CAAC;YAC5G,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC3C,CAAC;QAED,IAAI,CAAC;YACH,8EAA8E;YAC9E,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;QAChE,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IACjE,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC;IAE1D,IAAI,CAAC;QACH,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;IAChE,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex: a provider block in `~/.codex/config.toml`, checked with `codex login status`,
|
|
3
|
+
* verified with `codex exec`. User-level only: Codex ignores `model_provider` and
|
|
4
|
+
* `model_providers` in a project's `.codex/config.toml`.
|
|
5
|
+
*/
|
|
6
|
+
import { findOnPath } from "../../process.js";
|
|
7
|
+
import { codexHome, resolveCodexPaths, revertCodexConfig, writeCodexConfig } from "./config.js";
|
|
8
|
+
import { codexPlacementExample, codexTables, ROOT_LINE } from "./snippets.js";
|
|
9
|
+
import { CODEX_COMMAND, checkCodexLogin } from "./status.js";
|
|
10
|
+
import { verifyCodex } from "./verify.js";
|
|
11
|
+
const text = {
|
|
12
|
+
noSubscriptionOutcome: "no-codex-login",
|
|
13
|
+
noSubscription: {
|
|
14
|
+
"logged-out": {
|
|
15
|
+
headline: "No ChatGPT login detected for Codex.",
|
|
16
|
+
nextStep: "Run `codex login` and sign in with ChatGPT, then re-run this command.",
|
|
17
|
+
jsonReason: "no_chatgpt_login",
|
|
18
|
+
telemetryReason: "agent not logged in",
|
|
19
|
+
},
|
|
20
|
+
"api-key-login": {
|
|
21
|
+
headline: "Codex is signed in with an API key, not a ChatGPT login.",
|
|
22
|
+
nextStep: "The gateway forwards your ChatGPT login. Run `codex logout`, then `codex login` with ChatGPT, then re-run this command.",
|
|
23
|
+
jsonReason: "chatgpt_login_required",
|
|
24
|
+
telemetryReason: "agent logged in with an api key",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
verifiedVia: { "codex-exec": "`codex exec`" },
|
|
28
|
+
skippedBecause: "the Codex CLI was not found to verify with",
|
|
29
|
+
notInstalled: {
|
|
30
|
+
message: "The Codex CLI was not found. Install it, sign in with `codex login`, then re-run this command.",
|
|
31
|
+
jsonOutcome: "no-codex-cli",
|
|
32
|
+
jsonReason: "codex_cli_not_installed",
|
|
33
|
+
telemetryReason: "agent cli not installed",
|
|
34
|
+
},
|
|
35
|
+
checkingLogin: "Checking your Codex login…",
|
|
36
|
+
loginFound: "Codex login found",
|
|
37
|
+
};
|
|
38
|
+
export const codex = {
|
|
39
|
+
id: "codex",
|
|
40
|
+
kind: "codex",
|
|
41
|
+
displayName: "Codex",
|
|
42
|
+
configLabel: "config.toml",
|
|
43
|
+
targets: ["user"],
|
|
44
|
+
verifyFlags: [],
|
|
45
|
+
checkInstalled(_ctx, deps) {
|
|
46
|
+
// No stand-in: only the Codex CLI can send the ChatGPT login the gateway forwards.
|
|
47
|
+
return findOnPath(CODEX_COMMAND, deps.lookup) === undefined ? { kind: "missing" } : { kind: "present" };
|
|
48
|
+
},
|
|
49
|
+
resolvePaths(_target, env) {
|
|
50
|
+
return { ...resolveCodexPaths(codexHome(env)), verifyCwd: env.home };
|
|
51
|
+
},
|
|
52
|
+
preview(inputs) {
|
|
53
|
+
return {
|
|
54
|
+
text: codexPlacementExample(inputs),
|
|
55
|
+
json: { config: [ROOT_LINE, "", ...codexTables(inputs)].join("\n") },
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
write: writeCodexConfig,
|
|
59
|
+
revert: revertCodexConfig,
|
|
60
|
+
// The writer already masks the key in each conflict (see `want` in config.ts); a
|
|
61
|
+
// conflict value here is one key's value, with no header syntax left to match on.
|
|
62
|
+
redact: (value) => value,
|
|
63
|
+
warnings(_paths, processEnv) {
|
|
64
|
+
const found = [];
|
|
65
|
+
if (processEnv.OPENAI_BASE_URL !== undefined && processEnv.OPENAI_BASE_URL !== "") {
|
|
66
|
+
found.push({
|
|
67
|
+
code: "openai-base-url-set",
|
|
68
|
+
message: "OPENAI_BASE_URL is set in your environment. Codex has deprecated it, and it can send requests past the gateway — unset it if they do not show up.",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return found;
|
|
72
|
+
},
|
|
73
|
+
checkSubscription(paths, deps) {
|
|
74
|
+
return checkCodexLogin(paths.verifyCwd, deps);
|
|
75
|
+
},
|
|
76
|
+
verify: verifyCodex,
|
|
77
|
+
text,
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/agents/codex/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `install --client codex` writes into `~/.codex/config.toml`, built to match the
|
|
3
|
+
* webapp snippet byte for byte (AI21Labs/ai21-intelligent-gateway-webapp,
|
|
4
|
+
* `src/pages/docs/integrations.tsx:codexPlacementExample`). `test/fixtures` pins the
|
|
5
|
+
* two together; re-capture it when the webapp's snippet changes.
|
|
6
|
+
*
|
|
7
|
+
* Two parts, because they go to different places: the root `model_provider` line must
|
|
8
|
+
* sit above every `[table]` (TOML would otherwise read it as a key of the table before
|
|
9
|
+
* it), while the provider tables can go anywhere.
|
|
10
|
+
*
|
|
11
|
+
* One deliberate divergence, as for Claude Code: the webapp always emits
|
|
12
|
+
* `x-ai21-user-id`, having a signed-in user; here that line is absent unless
|
|
13
|
+
* `--user-id` supplies one. `x-ai21-client` is added on what the CLI writes only.
|
|
14
|
+
*/
|
|
15
|
+
import { type SnippetInputs } from "../types.js";
|
|
16
|
+
/** The root key that selects our provider. */
|
|
17
|
+
export declare const ROOT_LINE: string;
|
|
18
|
+
/** The header lines in contract order, as `[key, value]`. */
|
|
19
|
+
export declare function codexHeaders({ agentId, ai21Key, userId, client }: SnippetInputs): [string, string][];
|
|
20
|
+
/** The two provider tables, as lines. */
|
|
21
|
+
export declare function codexTables(inputs: SnippetInputs): string[];
|
|
22
|
+
/** The webapp's paste-in example, comments included. Also what `--print` shows. */
|
|
23
|
+
export declare function codexPlacementExample(inputs: SnippetInputs): string;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HEADERS_TABLE, PROVIDER_ID, PROVIDER_TABLE, tomlKey, tomlString } from "./toml.js";
|
|
2
|
+
/** The root key that selects our provider. */
|
|
3
|
+
export const ROOT_LINE = `model_provider = ${tomlString(PROVIDER_ID)}`;
|
|
4
|
+
/** The header lines in contract order, as `[key, value]`. */
|
|
5
|
+
export function codexHeaders({ agentId, ai21Key, userId, client }) {
|
|
6
|
+
const headers = [
|
|
7
|
+
["x-upstream", "openai-codex"],
|
|
8
|
+
["x-ai21-key", ai21Key],
|
|
9
|
+
["x-agent-id", agentId],
|
|
10
|
+
];
|
|
11
|
+
if (userId !== undefined)
|
|
12
|
+
headers.push(["x-ai21-user-id", userId]);
|
|
13
|
+
if (client !== undefined)
|
|
14
|
+
headers.push(["x-ai21-client", client]);
|
|
15
|
+
return headers;
|
|
16
|
+
}
|
|
17
|
+
/** The two provider tables, as lines. */
|
|
18
|
+
export function codexTables(inputs) {
|
|
19
|
+
return [
|
|
20
|
+
`[${PROVIDER_TABLE}]`,
|
|
21
|
+
`name = ${tomlString("AI21 Gateway")}`,
|
|
22
|
+
`base_url = ${tomlString(`${inputs.gatewayUrl}/v1`)}`,
|
|
23
|
+
`wire_api = "responses"`,
|
|
24
|
+
`requires_openai_auth = true`,
|
|
25
|
+
`[${HEADERS_TABLE}]`,
|
|
26
|
+
...codexHeaders(inputs).map(([key, value]) => `${tomlKey(key)} = ${tomlString(value)}`),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
/** The webapp's paste-in example, comments included. Also what `--print` shows. */
|
|
30
|
+
export function codexPlacementExample(inputs) {
|
|
31
|
+
return [
|
|
32
|
+
"# Adds to your existing ~/.codex/config.toml — nothing else changes.",
|
|
33
|
+
"# Keep model_provider above every [section]: it is a root key.",
|
|
34
|
+
ROOT_LINE,
|
|
35
|
+
"",
|
|
36
|
+
...codexTables(inputs),
|
|
37
|
+
].join("\n");
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=snippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.js","sourceRoot":"","sources":["../../../src/agents/codex/snippets.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5F,8CAA8C;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,oBAAoB,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;AAEvE,6DAA6D;AAC7D,MAAM,UAAU,YAAY,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAiB;IAC9E,MAAM,OAAO,GAAuB;QAClC,CAAC,YAAY,EAAE,cAAc,CAAC;QAC9B,CAAC,YAAY,EAAE,OAAO,CAAC;QACvB,CAAC,YAAY,EAAE,OAAO,CAAC;KACxB,CAAC;IACF,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IAEnE,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC;IAElE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,yCAAyC;AACzC,MAAM,UAAU,WAAW,CAAC,MAAqB;IAC/C,OAAO;QACL,IAAI,cAAc,GAAG;QACrB,UAAU,UAAU,CAAC,cAAc,CAAC,EAAE;QACtC,cAAc,UAAU,CAAC,GAAG,MAAM,CAAC,UAAU,KAAK,CAAC,EAAE;QACrD,wBAAwB;QACxB,6BAA6B;QAC7B,IAAI,aAAa,GAAG;QACpB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;KACxF,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IACzD,OAAO;QACL,sEAAsE;QACtE,gEAAgE;QAChE,SAAS;QACT,EAAE;QACF,GAAG,WAAW,CAAC,MAAM,CAAC;KACvB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentDeps, SubscriptionStatus } from "../types.js";
|
|
2
|
+
export declare const CODEX_COMMAND = "codex";
|
|
3
|
+
/**
|
|
4
|
+
* Runs `codex login status` and reads stderr. Only "Logged in using ChatGPT" counts
|
|
5
|
+
* as present; "Logged in using an API key" or "Not logged in" count as missing.
|
|
6
|
+
* An unrecognisable output, a missing binary or a timeout are all inconclusive.
|
|
7
|
+
*/
|
|
8
|
+
export declare function checkCodexLogin(cwd: string, deps: AgentDeps): Promise<SubscriptionStatus>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex login check with `codex login status`.
|
|
3
|
+
*/
|
|
4
|
+
import { findOnPath } from "../../process.js";
|
|
5
|
+
export const CODEX_COMMAND = "codex";
|
|
6
|
+
const STATUS_TIMEOUT_MS = 5_000;
|
|
7
|
+
/**
|
|
8
|
+
* Runs `codex login status` and reads stderr. Only "Logged in using ChatGPT" counts
|
|
9
|
+
* as present; "Logged in using an API key" or "Not logged in" count as missing.
|
|
10
|
+
* An unrecognisable output, a missing binary or a timeout are all inconclusive.
|
|
11
|
+
*/
|
|
12
|
+
export async function checkCodexLogin(cwd, deps) {
|
|
13
|
+
const executable = findOnPath(CODEX_COMMAND, deps.lookup);
|
|
14
|
+
if (executable === undefined)
|
|
15
|
+
return { kind: "inconclusive" };
|
|
16
|
+
const result = await deps.runCommand(executable, ["login", "status"], { cwd, timeoutMs: STATUS_TIMEOUT_MS });
|
|
17
|
+
if (result.timedOut || result.code === null)
|
|
18
|
+
return { kind: "inconclusive" };
|
|
19
|
+
// A broken config or missing CODEX_HOME makes the CLI exit 1 and print an error.
|
|
20
|
+
// That is not "definitely signed out"; it is "could not tell".
|
|
21
|
+
if (result.code === 1 && !/^(Not logged in|Logged in using an API key)/.test(result.output.trim())) {
|
|
22
|
+
return { kind: "inconclusive" };
|
|
23
|
+
}
|
|
24
|
+
if (result.code === 0 && /^Logged in using ChatGPT/.test(result.output.trim())) {
|
|
25
|
+
return { kind: "present" };
|
|
26
|
+
}
|
|
27
|
+
// "Logged in using an API key" without ChatGPT → not usable through the gateway.
|
|
28
|
+
if (result.code === 0 && /^Logged in using an API key/.test(result.output.trim())) {
|
|
29
|
+
return { kind: "missing", reason: "api-key-login" };
|
|
30
|
+
}
|
|
31
|
+
if (result.output.trim() === "Not logged in") {
|
|
32
|
+
return { kind: "missing", reason: "logged-out" };
|
|
33
|
+
}
|
|
34
|
+
return { kind: "inconclusive" };
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/agents/codex/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAErC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAEhC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,IAAe;IAChE,MAAM,UAAU,GAAG,UAAU,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAE9D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC7G,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAE7E,iFAAiF;IACjF,+DAA+D;IAC/D,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QACnG,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAClC,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/E,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAC7B,CAAC;IAED,iFAAiF;IACjF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,6BAA6B,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IACtD,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,eAAe,EAAE,CAAC;QAC7C,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IACnD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A targeted edit of `~/.codex/config.toml`: find the few things this tool owns, and
|
|
3
|
+
* replace or remove exactly those lines. Everything else — comments, ordering, blank
|
|
4
|
+
* lines, CRLF endings, tables we have never heard of — is carried through byte for byte.
|
|
5
|
+
*
|
|
6
|
+
* Not a TOML parser. It reads lines, and understands only what it must to stay safe:
|
|
7
|
+
* where a table starts, which root key a line assigns, and whether a line is inside a
|
|
8
|
+
* multi-line string (where a `[` is text, not a header). Anything it owns but cannot
|
|
9
|
+
* edit safely — our provider as dotted keys or an inline table — is reported as
|
|
10
|
+
* `unsupported`, and the caller refuses rather than guess.
|
|
11
|
+
*/
|
|
12
|
+
/** The provider id this tool writes. The webapp snippet uses the same one. */
|
|
13
|
+
export declare const PROVIDER_ID = "ai21";
|
|
14
|
+
/** The tables we own, in the order we write them. */
|
|
15
|
+
export declare const PROVIDER_TABLE = "model_providers.ai21";
|
|
16
|
+
export declare const HEADERS_TABLE = "model_providers.ai21.http_headers";
|
|
17
|
+
export interface Line {
|
|
18
|
+
/** Without its line ending. */
|
|
19
|
+
readonly text: string;
|
|
20
|
+
/** "\n", "\r\n", or "" for a last line with no newline. */
|
|
21
|
+
readonly eol: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function splitLines(raw: string): Line[];
|
|
24
|
+
export declare function joinLines(lines: readonly Line[]): string;
|
|
25
|
+
/** The file's own newline, so lines we add match the ones around them. */
|
|
26
|
+
export declare function newlineOf(lines: readonly Line[]): string;
|
|
27
|
+
export interface Region {
|
|
28
|
+
/** Index of the header line. */
|
|
29
|
+
readonly start: number;
|
|
30
|
+
/** One past the last line that belongs to the table (its header and its keys). */
|
|
31
|
+
readonly end: number;
|
|
32
|
+
}
|
|
33
|
+
export interface Scan {
|
|
34
|
+
readonly lines: Line[];
|
|
35
|
+
/** The root `model_provider = …` line, if any. */
|
|
36
|
+
readonly rootModelProvider?: number | undefined;
|
|
37
|
+
/** Index of the first table header; root keys live before it. */
|
|
38
|
+
readonly firstHeader: number;
|
|
39
|
+
readonly provider?: Region | undefined;
|
|
40
|
+
readonly headers?: Region | undefined;
|
|
41
|
+
/** Why we refuse to edit, when our provider is present in a form we do not handle. */
|
|
42
|
+
readonly unsupported?: string | undefined;
|
|
43
|
+
}
|
|
44
|
+
export declare function scan(raw: string): Scan;
|
|
45
|
+
/** A basic-string value's contents, or undefined when the line holds anything else. */
|
|
46
|
+
export declare function stringValue(text: string): string | undefined;
|
|
47
|
+
/** The `key = value` lines of a region, keyed by their normalised key. */
|
|
48
|
+
export declare function entries(scanned: Scan, region: Region | undefined): Map<string, string>;
|
|
49
|
+
/** Escapes a value for a TOML basic string. Control characters never reach here: args refuses them. */
|
|
50
|
+
export declare function tomlString(value: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Header keys need quoting in TOML only if they are not bare keys. Ours are all bare
|
|
53
|
+
* (`x-ai21-key`), but the rule is written down once rather than assumed at each site.
|
|
54
|
+
*/
|
|
55
|
+
export declare function tomlKey(key: string): string;
|
|
56
|
+
/** Drops the lines at `[start, end)` and any blank lines left directly above them. */
|
|
57
|
+
export declare function removeRange(lines: Line[], start: number, end: number): Line[];
|