@jacobbd/relay-ai 0.12.10 → 0.13.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/dist/{chunk-2KEDU24N.js → chunk-37GQTWDJ.js} +175 -627
- package/dist/chunk-37GQTWDJ.js.map +1 -0
- package/dist/{chunk-YIEEHFVL.js → chunk-4WUSKTVR.js} +2 -2
- package/dist/{chunk-OIL75EGI.js → chunk-LGQWKQKL.js} +542 -60
- package/dist/chunk-LGQWKQKL.js.map +1 -0
- package/dist/cli.js +313 -226
- package/dist/cli.js.map +1 -1
- package/dist/core/index.js +185 -32
- package/dist/core/index.js.map +1 -1
- package/dist/{manual-models-XV4TB7FB.js → manual-models-7BXJVEYR.js} +3 -3
- package/dist/{ui-command-CJYKHNG6.js → ui-command-QGVVDO63.js} +24 -24
- package/package.json +4 -3
- package/dist/chunk-2KEDU24N.js.map +0 -1
- package/dist/chunk-OIL75EGI.js.map +0 -1
- /package/dist/{chunk-YIEEHFVL.js.map → chunk-4WUSKTVR.js.map} +0 -0
- /package/dist/{manual-models-XV4TB7FB.js.map → manual-models-7BXJVEYR.js.map} +0 -0
- /package/dist/{ui-command-CJYKHNG6.js.map → ui-command-QGVVDO63.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
addManualModel,
|
|
4
4
|
removeManualModel
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4WUSKTVR.js";
|
|
6
6
|
import {
|
|
7
7
|
CODEX_APP_AUTO_COMPACT_RATIO,
|
|
8
8
|
CODEX_APP_PROVIDER_ID,
|
|
@@ -47,7 +47,6 @@ import {
|
|
|
47
47
|
fetchProviderCatalog,
|
|
48
48
|
fetchTemplateModels,
|
|
49
49
|
findBinaryOnPath,
|
|
50
|
-
findClaudeBinary,
|
|
51
50
|
findEmbeddedCodexBinary,
|
|
52
51
|
fmtCommand,
|
|
53
52
|
fmtCount,
|
|
@@ -63,7 +62,6 @@ import {
|
|
|
63
62
|
formatRegistryAuthLabel,
|
|
64
63
|
formatUpdateNotification,
|
|
65
64
|
getAntigravityDebugLogPath,
|
|
66
|
-
getAppPathOverride,
|
|
67
65
|
getClaudeDebugLogPath,
|
|
68
66
|
getCodexProxyDebugLogPath,
|
|
69
67
|
getGeminiProxyDebugLogPath,
|
|
@@ -77,11 +75,9 @@ import {
|
|
|
77
75
|
isFreeStatus,
|
|
78
76
|
isLikelyPlaceholderKey,
|
|
79
77
|
isOAuthImportProvider,
|
|
80
|
-
launchClaude,
|
|
81
78
|
launchOrRestartClaudeApp,
|
|
82
79
|
launchOrRestartCodexApp,
|
|
83
80
|
listCredentialSkippedProviders,
|
|
84
|
-
loadPreferences,
|
|
85
81
|
logActiveModel,
|
|
86
82
|
logConnected,
|
|
87
83
|
logProxy,
|
|
@@ -113,7 +109,6 @@ import {
|
|
|
113
109
|
quitClaudeAppGracefully,
|
|
114
110
|
quitCodexAppGracefully,
|
|
115
111
|
readBody,
|
|
116
|
-
recordLaunchSelection,
|
|
117
112
|
refreshAllProviderModels,
|
|
118
113
|
refreshModelsDevCacheAsync,
|
|
119
114
|
refreshProviderModels,
|
|
@@ -130,10 +125,7 @@ import {
|
|
|
130
125
|
resolveRefreshCredential,
|
|
131
126
|
resolveRelayCatalogSlots,
|
|
132
127
|
routableModelsForTarget,
|
|
133
|
-
runCodexCommand,
|
|
134
|
-
runCodexCommandSync,
|
|
135
128
|
runServerCommand,
|
|
136
|
-
savePreferences,
|
|
137
129
|
sendJson,
|
|
138
130
|
serializeCatalog,
|
|
139
131
|
shouldHideModel,
|
|
@@ -148,7 +140,7 @@ import {
|
|
|
148
140
|
waitForCodexAppQuit,
|
|
149
141
|
writeSecureLogLine,
|
|
150
142
|
zenRegistryStub
|
|
151
|
-
} from "./chunk-
|
|
143
|
+
} from "./chunk-37GQTWDJ.js";
|
|
152
144
|
import {
|
|
153
145
|
filterTemplates,
|
|
154
146
|
getTemplateById,
|
|
@@ -182,6 +174,7 @@ import {
|
|
|
182
174
|
formatUpstreamError,
|
|
183
175
|
formatUpstreamErrorTrace,
|
|
184
176
|
getAppHome,
|
|
177
|
+
getAppPathOverride,
|
|
185
178
|
getConfigPath,
|
|
186
179
|
getLogsPath,
|
|
187
180
|
getProviderModels,
|
|
@@ -191,6 +184,7 @@ import {
|
|
|
191
184
|
injectClaudeIdentity,
|
|
192
185
|
isSecretServiceAvailable,
|
|
193
186
|
isValidProviderId,
|
|
187
|
+
loadPreferences,
|
|
194
188
|
loadRegistry,
|
|
195
189
|
maxToolsForNpm,
|
|
196
190
|
migrateGlobalOpencodeCredential,
|
|
@@ -205,10 +199,14 @@ import {
|
|
|
205
199
|
readGlobalOpencodeCredential,
|
|
206
200
|
readOpencodeAuthFile,
|
|
207
201
|
readStoredProviderCredential,
|
|
202
|
+
recordLaunchSelection,
|
|
208
203
|
resolveApiKey,
|
|
209
204
|
resolveContextWindow,
|
|
210
205
|
resolveProviderCredential,
|
|
211
206
|
routeLookupIds,
|
|
207
|
+
runCodexCommand,
|
|
208
|
+
runCodexCommandSync,
|
|
209
|
+
savePreferences,
|
|
212
210
|
saveProviderCredential,
|
|
213
211
|
saveRegistry,
|
|
214
212
|
saveToCredentialStore,
|
|
@@ -222,7 +220,7 @@ import {
|
|
|
222
220
|
thinkingProviderOptions,
|
|
223
221
|
upstreamHttpStatus,
|
|
224
222
|
validateCustomEndpointUrl
|
|
225
|
-
} from "./chunk-
|
|
223
|
+
} from "./chunk-LGQWKQKL.js";
|
|
226
224
|
import "./chunk-JIDIH7DS.js";
|
|
227
225
|
|
|
228
226
|
// src/cli.ts
|
|
@@ -231,41 +229,124 @@ import * as p15 from "@clack/prompts";
|
|
|
231
229
|
import { realpathSync } from "fs";
|
|
232
230
|
import { fileURLToPath } from "url";
|
|
233
231
|
|
|
232
|
+
// src/launch.ts
|
|
233
|
+
import { execSync } from "child_process";
|
|
234
|
+
import spawn from "cross-spawn";
|
|
235
|
+
import { existsSync, appendFileSync } from "fs";
|
|
236
|
+
import { homedir } from "os";
|
|
237
|
+
import { join } from "path";
|
|
238
|
+
var isWindows = process.platform === "win32";
|
|
239
|
+
var FALLBACK_PATHS = isWindows ? [
|
|
240
|
+
join(process.env["APPDATA"] ?? homedir(), "npm", "claude.cmd"),
|
|
241
|
+
join(process.env["APPDATA"] ?? homedir(), "npm", "claude"),
|
|
242
|
+
join(homedir(), "AppData", "Roaming", "npm", "claude.cmd")
|
|
243
|
+
] : [
|
|
244
|
+
join(homedir(), ".local", "bin", "claude"),
|
|
245
|
+
join(homedir(), ".npm", "bin", "claude"),
|
|
246
|
+
"/usr/local/bin/claude",
|
|
247
|
+
"/opt/homebrew/bin/claude"
|
|
248
|
+
];
|
|
249
|
+
function findClaudeBinary() {
|
|
250
|
+
const override = getAppPathOverride("claude");
|
|
251
|
+
if (override) return existsSync(override) ? override : null;
|
|
252
|
+
return findBinaryOnPath("claude", FALLBACK_PATHS);
|
|
253
|
+
}
|
|
254
|
+
function buildClaudeArgs(model, extraArgs) {
|
|
255
|
+
return model ? ["--model", model, ...extraArgs] : [...extraArgs];
|
|
256
|
+
}
|
|
257
|
+
function launchClaude(env, model, extraArgs) {
|
|
258
|
+
return new Promise((resolve2) => {
|
|
259
|
+
const claudePath = findClaudeBinary();
|
|
260
|
+
const args = buildClaudeArgs(model, extraArgs);
|
|
261
|
+
const debugFileIdx = extraArgs.indexOf("--debug-file");
|
|
262
|
+
const debugLogPath = debugFileIdx !== -1 && extraArgs[debugFileIdx + 1] ? extraArgs[debugFileIdx + 1] : void 0;
|
|
263
|
+
const originalStdoutWrite = process.stdout.write;
|
|
264
|
+
const originalStderrWrite = process.stderr.write;
|
|
265
|
+
const muteWrite = (chunk, encoding, callback) => {
|
|
266
|
+
if (typeof encoding === "function") {
|
|
267
|
+
callback = encoding;
|
|
268
|
+
}
|
|
269
|
+
if (debugLogPath) {
|
|
270
|
+
try {
|
|
271
|
+
const str = typeof chunk === "string" ? chunk : new TextDecoder().decode(chunk);
|
|
272
|
+
appendFileSync(debugLogPath, `[parent] ${str}`);
|
|
273
|
+
} catch {
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (callback) callback();
|
|
277
|
+
return true;
|
|
278
|
+
};
|
|
279
|
+
process.stdout.write = muteWrite;
|
|
280
|
+
process.stderr.write = muteWrite;
|
|
281
|
+
const restore = () => {
|
|
282
|
+
process.stdout.write = originalStdoutWrite;
|
|
283
|
+
process.stderr.write = originalStderrWrite;
|
|
284
|
+
};
|
|
285
|
+
const child = spawn(claudePath, args, {
|
|
286
|
+
stdio: "inherit",
|
|
287
|
+
env
|
|
288
|
+
});
|
|
289
|
+
const forward = (signal) => {
|
|
290
|
+
child.kill(signal);
|
|
291
|
+
};
|
|
292
|
+
const onSigint = () => forward("SIGINT");
|
|
293
|
+
const onSigterm = () => forward("SIGTERM");
|
|
294
|
+
const onSighup = () => forward("SIGHUP");
|
|
295
|
+
const cleanup = () => {
|
|
296
|
+
restore();
|
|
297
|
+
process.off("SIGINT", onSigint);
|
|
298
|
+
process.off("SIGTERM", onSigterm);
|
|
299
|
+
process.off("SIGHUP", onSighup);
|
|
300
|
+
};
|
|
301
|
+
process.once("SIGINT", onSigint);
|
|
302
|
+
process.once("SIGTERM", onSigterm);
|
|
303
|
+
process.once("SIGHUP", onSighup);
|
|
304
|
+
child.on("exit", (code) => {
|
|
305
|
+
cleanup();
|
|
306
|
+
resolve2(code ?? 0);
|
|
307
|
+
});
|
|
308
|
+
child.on("error", (err) => {
|
|
309
|
+
cleanup();
|
|
310
|
+
resolve2(1);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
234
315
|
// src/first-run.ts
|
|
235
316
|
import pc from "picocolors";
|
|
236
317
|
import * as p2 from "@clack/prompts";
|
|
237
318
|
|
|
238
319
|
// src/opencode-serve.ts
|
|
239
|
-
import { execSync, spawn } from "child_process";
|
|
320
|
+
import { execSync as execSync2, spawn as spawn2 } from "child_process";
|
|
240
321
|
import { randomBytes } from "crypto";
|
|
241
|
-
import { existsSync } from "fs";
|
|
242
|
-
import { homedir } from "os";
|
|
243
|
-
import { join } from "path";
|
|
244
|
-
var
|
|
245
|
-
var OPENCODE_FALLBACK_PATHS =
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
322
|
+
import { existsSync as existsSync2 } from "fs";
|
|
323
|
+
import { homedir as homedir2 } from "os";
|
|
324
|
+
import { join as join2 } from "path";
|
|
325
|
+
var isWindows2 = process.platform === "win32";
|
|
326
|
+
var OPENCODE_FALLBACK_PATHS = isWindows2 ? [
|
|
327
|
+
join2(process.env["APPDATA"] ?? homedir2(), "npm", "opencode.cmd"),
|
|
328
|
+
join2(process.env["APPDATA"] ?? homedir2(), "npm", "opencode"),
|
|
329
|
+
join2(homedir2(), "AppData", "Roaming", "npm", "opencode.cmd")
|
|
249
330
|
] : [
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
331
|
+
join2(homedir2(), ".opencode", "bin", "opencode"),
|
|
332
|
+
join2(homedir2(), ".local", "bin", "opencode"),
|
|
333
|
+
join2(homedir2(), ".npm", "bin", "opencode"),
|
|
253
334
|
"/usr/local/bin/opencode",
|
|
254
335
|
"/opt/homebrew/bin/opencode"
|
|
255
336
|
];
|
|
256
337
|
function findOpencodeBinary() {
|
|
257
338
|
try {
|
|
258
|
-
const result =
|
|
339
|
+
const result = execSync2(isWindows2 ? "where.exe opencode" : "which opencode", {
|
|
259
340
|
encoding: "utf8",
|
|
260
341
|
stdio: ["pipe", "pipe", "pipe"]
|
|
261
342
|
});
|
|
262
343
|
const lines = result.trim().split("\n").map((l) => l.trim()).filter(Boolean);
|
|
263
|
-
const path3 = (
|
|
344
|
+
const path3 = (isWindows2 ? lines.find((l) => l.toLowerCase().endsWith(".cmd")) : null) ?? lines[0];
|
|
264
345
|
if (path3) return path3;
|
|
265
346
|
} catch {
|
|
266
347
|
}
|
|
267
348
|
for (const path3 of OPENCODE_FALLBACK_PATHS) {
|
|
268
|
-
if (
|
|
349
|
+
if (existsSync2(path3)) return path3;
|
|
269
350
|
}
|
|
270
351
|
return null;
|
|
271
352
|
}
|
|
@@ -376,10 +457,10 @@ async function fetchRawOpencodeProviders() {
|
|
|
376
457
|
finish(null);
|
|
377
458
|
}, TIMEOUT_MS);
|
|
378
459
|
try {
|
|
379
|
-
child =
|
|
460
|
+
child = isWindows2 ? spawn2("cmd.exe", ["/c", binary, "serve", "--port", "0"], {
|
|
380
461
|
stdio: ["pipe", "pipe", "pipe"],
|
|
381
462
|
env: { ...process.env, OPENCODE_SERVER_PASSWORD: password3 }
|
|
382
|
-
}) :
|
|
463
|
+
}) : spawn2(binary, ["serve", "--port", "0"], {
|
|
383
464
|
stdio: ["pipe", "pipe", "pipe"],
|
|
384
465
|
env: { ...process.env, OPENCODE_SERVER_PASSWORD: password3 }
|
|
385
466
|
});
|
|
@@ -687,23 +768,23 @@ async function importFromOpencode(options = {}) {
|
|
|
687
768
|
|
|
688
769
|
// src/key-setup.ts
|
|
689
770
|
import * as p from "@clack/prompts";
|
|
690
|
-
import { appendFileSync, readFileSync, existsSync as
|
|
691
|
-
import { homedir as
|
|
771
|
+
import { appendFileSync as appendFileSync2, readFileSync, existsSync as existsSync3 } from "fs";
|
|
772
|
+
import { homedir as homedir3 } from "os";
|
|
692
773
|
import { spawnSync } from "child_process";
|
|
693
774
|
function detectShellProfile() {
|
|
694
775
|
const shell = process.env["SHELL"] ?? "";
|
|
695
776
|
if (process.platform === "darwin") {
|
|
696
|
-
if (shell.includes("zsh")) return { display: "~/.zshrc", path: `${
|
|
697
|
-
if (shell.includes("bash")) return { display: "~/.bash_profile", path: `${
|
|
698
|
-
return { display: "~/.profile", path: `${
|
|
777
|
+
if (shell.includes("zsh")) return { display: "~/.zshrc", path: `${homedir3()}/.zshrc` };
|
|
778
|
+
if (shell.includes("bash")) return { display: "~/.bash_profile", path: `${homedir3()}/.bash_profile` };
|
|
779
|
+
return { display: "~/.profile", path: `${homedir3()}/.profile` };
|
|
699
780
|
}
|
|
700
781
|
if (process.platform === "linux") {
|
|
701
|
-
if (shell.includes("zsh")) return { display: "~/.zshrc", path: `${
|
|
702
|
-
if (shell.includes("bash")) return { display: "~/.bashrc", path: `${
|
|
703
|
-
return { display: "~/.profile", path: `${
|
|
782
|
+
if (shell.includes("zsh")) return { display: "~/.zshrc", path: `${homedir3()}/.zshrc` };
|
|
783
|
+
if (shell.includes("bash")) return { display: "~/.bashrc", path: `${homedir3()}/.bashrc` };
|
|
784
|
+
return { display: "~/.profile", path: `${homedir3()}/.profile` };
|
|
704
785
|
}
|
|
705
|
-
if (shell.includes("bash")) return { display: "~/.bashrc", path: `${
|
|
706
|
-
return { display: "~/.profile", path: `${
|
|
786
|
+
if (shell.includes("bash")) return { display: "~/.bashrc", path: `${homedir3()}/.bashrc` };
|
|
787
|
+
return { display: "~/.profile", path: `${homedir3()}/.profile` };
|
|
707
788
|
}
|
|
708
789
|
async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
709
790
|
if (!simulate) {
|
|
@@ -711,7 +792,7 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
711
792
|
if (existing) return existing;
|
|
712
793
|
}
|
|
713
794
|
const isMac = process.platform === "darwin";
|
|
714
|
-
const
|
|
795
|
+
const isWindows6 = process.platform === "win32";
|
|
715
796
|
const isLinux = process.platform === "linux";
|
|
716
797
|
if (simulate) {
|
|
717
798
|
printDryRunPanel();
|
|
@@ -725,7 +806,7 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
725
806
|
};
|
|
726
807
|
const storedKey = await readFromCredentialStore(keyDiag);
|
|
727
808
|
if (storedKey) {
|
|
728
|
-
const storeName = isMac ? "macOS Keychain" :
|
|
809
|
+
const storeName = isMac ? "macOS Keychain" : isWindows6 ? "Windows Credential Manager" : "Secret Service";
|
|
729
810
|
p.log.success(`Found key in ${storeName}`);
|
|
730
811
|
process.env["OPENCODE_API_KEY"] = storedKey;
|
|
731
812
|
return storedKey;
|
|
@@ -755,7 +836,7 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
755
836
|
{ value: "session", label: "This session only", hint: "Not saved anywhere \u2014 you'll be asked again next time" }
|
|
756
837
|
];
|
|
757
838
|
}
|
|
758
|
-
if (
|
|
839
|
+
if (isWindows6) {
|
|
759
840
|
return [
|
|
760
841
|
{ value: "credential-manager", label: "Windows Credential Manager", hint: "Key stored securely; relay-ai reads it automatically next time" },
|
|
761
842
|
{ value: "setx", label: "Persistent environment variable (plaintext)", hint: "Runs setx \u2014 key visible in System Properties \u2192 Environment Variables" },
|
|
@@ -777,7 +858,7 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
777
858
|
const saveChoice = await p.select({
|
|
778
859
|
message: "Where should we save the key?",
|
|
779
860
|
options: saveOptions,
|
|
780
|
-
initialValue: isMac ? "keychain" :
|
|
861
|
+
initialValue: isMac ? "keychain" : isWindows6 ? "credential-manager" : secretServiceAvailable ? "secret-service" : "profile"
|
|
781
862
|
});
|
|
782
863
|
if (p.isCancel(saveChoice)) {
|
|
783
864
|
p.cancel("Cancelled.");
|
|
@@ -804,9 +885,9 @@ async function resolveOrCollectApiKey(simulate = false, trace = false) {
|
|
|
804
885
|
if (await saveToCredentialStore(trimmedKey)) {
|
|
805
886
|
try {
|
|
806
887
|
const autoLoadLine = `export OPENCODE_API_KEY="$(security find-generic-password -s relay-ai -a ${GLOBAL_OPENCODE_KEYRING_ACCOUNT} -w 2>/dev/null)"`;
|
|
807
|
-
const existing =
|
|
888
|
+
const existing = existsSync3(path3) ? readFileSync(path3, "utf8") : "";
|
|
808
889
|
if (!existing.includes(autoLoadLine)) {
|
|
809
|
-
|
|
890
|
+
appendFileSync2(path3, `
|
|
810
891
|
# relay-ai: load API key from macOS Keychain
|
|
811
892
|
${autoLoadLine}
|
|
812
893
|
`);
|
|
@@ -841,9 +922,9 @@ ${autoLoadLine}
|
|
|
841
922
|
}
|
|
842
923
|
} else if (saveChoice === "profile") {
|
|
843
924
|
try {
|
|
844
|
-
if (!
|
|
925
|
+
if (!existsSync3(path3)) appendFileSync2(path3, "");
|
|
845
926
|
const escapedKey = trimmedKey.replace(/'/g, "'\\''");
|
|
846
|
-
|
|
927
|
+
appendFileSync2(path3, `
|
|
847
928
|
export OPENCODE_API_KEY='${escapedKey}'
|
|
848
929
|
`);
|
|
849
930
|
p.log.success(`Key saved to ${display} \u2014 active now and in all future terminals.`);
|
|
@@ -2418,7 +2499,7 @@ async function runProvidersCommand(args) {
|
|
|
2418
2499
|
// src/codex.ts
|
|
2419
2500
|
import pc7 from "picocolors";
|
|
2420
2501
|
import * as p9 from "@clack/prompts";
|
|
2421
|
-
import { join as
|
|
2502
|
+
import { join as join7 } from "path";
|
|
2422
2503
|
|
|
2423
2504
|
// src/codex-proxy.ts
|
|
2424
2505
|
import { createHash as createHash3 } from "crypto";
|
|
@@ -4034,7 +4115,7 @@ async function resolveRoutedCollaborationInput(input, context) {
|
|
|
4034
4115
|
|
|
4035
4116
|
// src/codex/route-audit.ts
|
|
4036
4117
|
import { chmodSync, mkdirSync, writeFileSync } from "fs";
|
|
4037
|
-
import { join as
|
|
4118
|
+
import { join as join3 } from "path";
|
|
4038
4119
|
var DIR_MODE = 448;
|
|
4039
4120
|
var FILE_MODE = 384;
|
|
4040
4121
|
var CODEX_ROUTE_AUDIT_LOG = "codex-route-audit.jsonl";
|
|
@@ -4063,7 +4144,7 @@ function getCodexRouteAuditLogPath() {
|
|
|
4063
4144
|
chmodSync(dir, DIR_MODE);
|
|
4064
4145
|
} catch {
|
|
4065
4146
|
}
|
|
4066
|
-
return
|
|
4147
|
+
return join3(dir, CODEX_ROUTE_AUDIT_LOG);
|
|
4067
4148
|
}
|
|
4068
4149
|
function prepareCodexRouteAuditLog(path3 = getCodexRouteAuditLogPath()) {
|
|
4069
4150
|
writeFileSync(path3, "", { mode: FILE_MODE });
|
|
@@ -5422,13 +5503,13 @@ data: ${JSON.stringify({ error: { message: `Unknown model: ${modelId}` } })}
|
|
|
5422
5503
|
}
|
|
5423
5504
|
|
|
5424
5505
|
// src/codex/profile.ts
|
|
5425
|
-
import { join as
|
|
5506
|
+
import { join as join5 } from "path";
|
|
5426
5507
|
|
|
5427
5508
|
// src/codex/session.ts
|
|
5428
5509
|
import {
|
|
5429
5510
|
copyFileSync,
|
|
5430
5511
|
chmodSync as chmodSync2,
|
|
5431
|
-
existsSync as
|
|
5512
|
+
existsSync as existsSync4,
|
|
5432
5513
|
mkdirSync as mkdirSync2,
|
|
5433
5514
|
readdirSync,
|
|
5434
5515
|
readFileSync as readFileSync2,
|
|
@@ -5438,44 +5519,44 @@ import {
|
|
|
5438
5519
|
unlinkSync,
|
|
5439
5520
|
writeFileSync as writeFileSync2
|
|
5440
5521
|
} from "fs";
|
|
5441
|
-
import { homedir as
|
|
5442
|
-
import { basename, dirname, join as
|
|
5522
|
+
import { homedir as homedir4 } from "os";
|
|
5523
|
+
import { basename, dirname, join as join4 } from "path";
|
|
5443
5524
|
var CODEX_PROFILE_NAME = "relay-ai-launch";
|
|
5444
5525
|
var STALE_SESSION_MS = 5 * 60 * 1e3;
|
|
5445
5526
|
var MAX_BACKUPS = 5;
|
|
5446
5527
|
function getCodexHome(env = process.env) {
|
|
5447
|
-
return env["CODEX_HOME"] ||
|
|
5528
|
+
return env["CODEX_HOME"] || join4(homedir4(), ".codex");
|
|
5448
5529
|
}
|
|
5449
5530
|
function getCodexProfilePath() {
|
|
5450
|
-
return
|
|
5531
|
+
return join4(getCodexHome(), `${CODEX_PROFILE_NAME}.config.toml`);
|
|
5451
5532
|
}
|
|
5452
5533
|
function getRelayAiCodexDir(env = process.env) {
|
|
5453
|
-
return
|
|
5534
|
+
return join4(getAppHome(env), "codex");
|
|
5454
5535
|
}
|
|
5455
5536
|
function getSessionLockPath(env = process.env) {
|
|
5456
|
-
return
|
|
5537
|
+
return join4(getRelayAiCodexDir(env), "session.json");
|
|
5457
5538
|
}
|
|
5458
5539
|
function getBackupsDir(env = process.env) {
|
|
5459
|
-
return
|
|
5540
|
+
return join4(getRelayAiCodexDir(env), "backups");
|
|
5460
5541
|
}
|
|
5461
5542
|
function getCatalogPath(providerId, env = process.env) {
|
|
5462
|
-
return
|
|
5543
|
+
return join4(getRelayAiCodexDir(env), `models-${providerId}.json`);
|
|
5463
5544
|
}
|
|
5464
5545
|
function ownedOverlayPaths(env = process.env) {
|
|
5465
5546
|
const paths = [getCodexProfilePath()];
|
|
5466
5547
|
const codexDir = getRelayAiCodexDir(env);
|
|
5467
|
-
if (
|
|
5548
|
+
if (existsSync4(codexDir)) {
|
|
5468
5549
|
for (const name of readdirSync(codexDir)) {
|
|
5469
5550
|
if (name.startsWith("models-") && name.endsWith(".json")) {
|
|
5470
|
-
paths.push(
|
|
5551
|
+
paths.push(join4(codexDir, name));
|
|
5471
5552
|
}
|
|
5472
5553
|
}
|
|
5473
5554
|
}
|
|
5474
|
-
const agentsDir =
|
|
5475
|
-
if (
|
|
5555
|
+
const agentsDir = join4(getCodexHome(env), "agents");
|
|
5556
|
+
if (existsSync4(agentsDir)) {
|
|
5476
5557
|
for (const name of readdirSync(agentsDir)) {
|
|
5477
5558
|
if (/^relay-model-[a-z0-9-]+\.toml$/i.test(name)) {
|
|
5478
|
-
paths.push(
|
|
5559
|
+
paths.push(join4(agentsDir, name));
|
|
5479
5560
|
}
|
|
5480
5561
|
}
|
|
5481
5562
|
}
|
|
@@ -5493,17 +5574,17 @@ function atomicWriteFile(path3, content) {
|
|
|
5493
5574
|
}
|
|
5494
5575
|
}
|
|
5495
5576
|
function rotateBackups(filePath, env = process.env) {
|
|
5496
|
-
if (!
|
|
5577
|
+
if (!existsSync4(filePath)) return;
|
|
5497
5578
|
const backupsDir = getBackupsDir(env);
|
|
5498
5579
|
mkdirSync2(backupsDir, { recursive: true });
|
|
5499
5580
|
const base = basename(filePath);
|
|
5500
5581
|
const stamp = Date.now();
|
|
5501
|
-
const backupPath =
|
|
5582
|
+
const backupPath = join4(backupsDir, `${base}.${stamp}.bak`);
|
|
5502
5583
|
copyFileSync(filePath, backupPath);
|
|
5503
|
-
const backups = readdirSync(backupsDir).filter((n) => n.startsWith(`${base}.`) && n.endsWith(".bak")).map((n) => ({ name: n, mtime: statSync(
|
|
5584
|
+
const backups = readdirSync(backupsDir).filter((n) => n.startsWith(`${base}.`) && n.endsWith(".bak")).map((n) => ({ name: n, mtime: statSync(join4(backupsDir, n)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
5504
5585
|
for (const old of backups.slice(MAX_BACKUPS)) {
|
|
5505
5586
|
try {
|
|
5506
|
-
unlinkSync(
|
|
5587
|
+
unlinkSync(join4(backupsDir, old.name));
|
|
5507
5588
|
} catch {
|
|
5508
5589
|
}
|
|
5509
5590
|
}
|
|
@@ -5514,7 +5595,7 @@ function writeOverlayFile(path3, content, env = process.env) {
|
|
|
5514
5595
|
}
|
|
5515
5596
|
function readSessionLock(env = process.env) {
|
|
5516
5597
|
const path3 = getSessionLockPath(env);
|
|
5517
|
-
if (!
|
|
5598
|
+
if (!existsSync4(path3)) return null;
|
|
5518
5599
|
try {
|
|
5519
5600
|
const parsed = JSON.parse(readFileSync2(path3, "utf8"));
|
|
5520
5601
|
if (typeof parsed.pid === "number" && typeof parsed.startedAt === "string") return parsed;
|
|
@@ -5543,7 +5624,7 @@ function isConcurrentSession(lock) {
|
|
|
5543
5624
|
function restoreCodexOverlay(env = process.env) {
|
|
5544
5625
|
const removed = [];
|
|
5545
5626
|
for (const path3 of ownedOverlayPaths(env)) {
|
|
5546
|
-
if (!
|
|
5627
|
+
if (!existsSync4(path3)) continue;
|
|
5547
5628
|
try {
|
|
5548
5629
|
rmSync(path3, { force: true });
|
|
5549
5630
|
removed.push(path3);
|
|
@@ -5553,7 +5634,7 @@ function restoreCodexOverlay(env = process.env) {
|
|
|
5553
5634
|
return removed;
|
|
5554
5635
|
}
|
|
5555
5636
|
function remainingOverlayPaths(env = process.env) {
|
|
5556
|
-
return ownedOverlayPaths(env).filter((p16) =>
|
|
5637
|
+
return ownedOverlayPaths(env).filter((p16) => existsSync4(p16));
|
|
5557
5638
|
}
|
|
5558
5639
|
function recoverInterruptedCodexSession(env = process.env) {
|
|
5559
5640
|
const before = remainingOverlayPaths(env);
|
|
@@ -5647,22 +5728,22 @@ function getCatalogOutputPath(providerId) {
|
|
|
5647
5728
|
return getCatalogPath(providerId);
|
|
5648
5729
|
}
|
|
5649
5730
|
function getFavoritesCatalogPath() {
|
|
5650
|
-
return
|
|
5731
|
+
return join5(getRelayAiCodexDir(), "models-favorites.json");
|
|
5651
5732
|
}
|
|
5652
5733
|
function getFavoritesAppCatalogPath() {
|
|
5653
|
-
return
|
|
5734
|
+
return join5(getRelayAiCodexDir(), "app-models-favorites.json");
|
|
5654
5735
|
}
|
|
5655
5736
|
function profileName() {
|
|
5656
5737
|
return CODEX_PROFILE_NAME;
|
|
5657
5738
|
}
|
|
5658
5739
|
|
|
5659
5740
|
// src/codex/launch.ts
|
|
5660
|
-
import { execSync as
|
|
5661
|
-
import
|
|
5662
|
-
import { existsSync as
|
|
5663
|
-
import { homedir as
|
|
5664
|
-
import { join as
|
|
5665
|
-
var
|
|
5741
|
+
import { execSync as execSync3 } from "child_process";
|
|
5742
|
+
import spawn3 from "cross-spawn";
|
|
5743
|
+
import { existsSync as existsSync5 } from "fs";
|
|
5744
|
+
import { homedir as homedir5 } from "os";
|
|
5745
|
+
import { join as join6 } from "path";
|
|
5746
|
+
var isWindows3 = process.platform === "win32";
|
|
5666
5747
|
var CODEX_CI_ENV_VARS = [
|
|
5667
5748
|
"CI",
|
|
5668
5749
|
"CODEX_CI",
|
|
@@ -5681,33 +5762,33 @@ function stripCodexInheritedEnv(env) {
|
|
|
5681
5762
|
}
|
|
5682
5763
|
return out;
|
|
5683
5764
|
}
|
|
5684
|
-
var CODEX_FALLBACK_PATHS =
|
|
5685
|
-
|
|
5686
|
-
|
|
5765
|
+
var CODEX_FALLBACK_PATHS = isWindows3 ? [
|
|
5766
|
+
join6(process.env["APPDATA"] ?? homedir5(), "npm", "codex.cmd"),
|
|
5767
|
+
join6(process.env["APPDATA"] ?? homedir5(), "npm", "codex")
|
|
5687
5768
|
] : [
|
|
5688
|
-
|
|
5689
|
-
|
|
5769
|
+
join6(homedir5(), ".local", "bin", "codex"),
|
|
5770
|
+
join6(homedir5(), ".npm", "bin", "codex"),
|
|
5690
5771
|
"/usr/local/bin/codex",
|
|
5691
5772
|
"/opt/homebrew/bin/codex"
|
|
5692
5773
|
];
|
|
5693
5774
|
function findCodexBinary() {
|
|
5694
5775
|
const override = getAppPathOverride("codex");
|
|
5695
|
-
if (override) return selectCodexBinary([override],
|
|
5776
|
+
if (override) return selectCodexBinary([override], existsSync5, canRunCodexBinary);
|
|
5696
5777
|
const candidates = [];
|
|
5697
5778
|
try {
|
|
5698
|
-
const result =
|
|
5779
|
+
const result = execSync3(isWindows3 ? "where.exe codex" : "which codex", {
|
|
5699
5780
|
encoding: "utf8",
|
|
5700
5781
|
stdio: ["pipe", "pipe", "pipe"]
|
|
5701
5782
|
});
|
|
5702
5783
|
const lines = result.trim().split("\n").map((l) => l.trim()).filter(Boolean);
|
|
5703
|
-
if (
|
|
5784
|
+
if (isWindows3) {
|
|
5704
5785
|
candidates.push(...lines.filter((l) => l.toLowerCase().endsWith(".cmd")));
|
|
5705
5786
|
}
|
|
5706
5787
|
candidates.push(...lines);
|
|
5707
5788
|
} catch {
|
|
5708
5789
|
}
|
|
5709
5790
|
candidates.push(...CODEX_FALLBACK_PATHS);
|
|
5710
|
-
return selectCodexBinary(candidates,
|
|
5791
|
+
return selectCodexBinary(candidates, existsSync5, canRunCodexBinary);
|
|
5711
5792
|
}
|
|
5712
5793
|
function selectCodexBinary(candidates, exists, canRun) {
|
|
5713
5794
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -5757,7 +5838,7 @@ function launchCodex(modelId, env, extraArgs) {
|
|
|
5757
5838
|
return new Promise((resolve2) => {
|
|
5758
5839
|
const codexPath = findCodexBinary();
|
|
5759
5840
|
const args = ["--profile", profileName(), "-m", modelId, ...ensureCodexSandboxArgs(extraArgs)];
|
|
5760
|
-
const child =
|
|
5841
|
+
const child = spawn3(codexPath, args, {
|
|
5761
5842
|
stdio: "inherit",
|
|
5762
5843
|
env
|
|
5763
5844
|
});
|
|
@@ -6730,7 +6811,7 @@ async function writeFavoritesLaunchArtifacts(resolved, starting, proxyPort) {
|
|
|
6730
6811
|
return { profilePath, catalogPath };
|
|
6731
6812
|
}
|
|
6732
6813
|
async function writeMixedLaunchArtifacts(plan, proxyPort) {
|
|
6733
|
-
const catalogPath =
|
|
6814
|
+
const catalogPath = join7(getRelayAiCodexDir(), "models-mixed.json");
|
|
6734
6815
|
writeOverlayFile(catalogPath, serializeCatalog(plan.catalog));
|
|
6735
6816
|
const profilePath = getProfileOutputPath();
|
|
6736
6817
|
writeOverlayFile(profilePath, buildCodexMixedProfileToml({
|
|
@@ -7314,24 +7395,24 @@ import pc8 from "picocolors";
|
|
|
7314
7395
|
import * as p11 from "@clack/prompts";
|
|
7315
7396
|
|
|
7316
7397
|
// src/gemini/launch.ts
|
|
7317
|
-
import { spawn as
|
|
7318
|
-
import { existsSync as
|
|
7319
|
-
import { homedir as
|
|
7320
|
-
import { join as
|
|
7321
|
-
var
|
|
7398
|
+
import { spawn as spawn4 } from "child_process";
|
|
7399
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync3, mkdtempSync, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
7400
|
+
import { homedir as homedir6, tmpdir } from "os";
|
|
7401
|
+
import { join as join8 } from "path";
|
|
7402
|
+
var isWindows4 = process.platform === "win32";
|
|
7322
7403
|
var GEMINI_API_KEY_AUTH_TYPE = "gemini-api-key";
|
|
7323
|
-
var GEMINI_FALLBACK_PATHS =
|
|
7324
|
-
|
|
7325
|
-
|
|
7404
|
+
var GEMINI_FALLBACK_PATHS = isWindows4 ? [
|
|
7405
|
+
join8(process.env["APPDATA"] ?? homedir6(), "npm", "gemini.cmd"),
|
|
7406
|
+
join8(process.env["APPDATA"] ?? homedir6(), "npm", "gemini")
|
|
7326
7407
|
] : [
|
|
7327
|
-
|
|
7328
|
-
|
|
7408
|
+
join8(homedir6(), ".local", "bin", "gemini"),
|
|
7409
|
+
join8(homedir6(), ".npm", "bin", "gemini"),
|
|
7329
7410
|
"/usr/local/bin/gemini",
|
|
7330
7411
|
"/opt/homebrew/bin/gemini"
|
|
7331
7412
|
];
|
|
7332
7413
|
function findGeminiBinary() {
|
|
7333
7414
|
const override = getAppPathOverride("gemini");
|
|
7334
|
-
if (override) return
|
|
7415
|
+
if (override) return existsSync6(override) ? override : null;
|
|
7335
7416
|
return findBinaryOnPath("gemini", GEMINI_FALLBACK_PATHS);
|
|
7336
7417
|
}
|
|
7337
7418
|
function buildGeminiChildEnv(proxyPort, proxyToken) {
|
|
@@ -7346,7 +7427,7 @@ function buildGeminiChildEnv(proxyPort, proxyToken) {
|
|
|
7346
7427
|
return env;
|
|
7347
7428
|
}
|
|
7348
7429
|
function createGeminiCliHomeOverlay() {
|
|
7349
|
-
const cliHome = mkdtempSync(
|
|
7430
|
+
const cliHome = mkdtempSync(join8(tmpdir(), "relay-ai-gemini-"));
|
|
7350
7431
|
const settings = {
|
|
7351
7432
|
security: {
|
|
7352
7433
|
auth: {
|
|
@@ -7354,9 +7435,9 @@ function createGeminiCliHomeOverlay() {
|
|
|
7354
7435
|
}
|
|
7355
7436
|
}
|
|
7356
7437
|
};
|
|
7357
|
-
const geminiDir =
|
|
7438
|
+
const geminiDir = join8(cliHome, ".gemini");
|
|
7358
7439
|
mkdirSync3(geminiDir);
|
|
7359
|
-
writeFileSync3(
|
|
7440
|
+
writeFileSync3(join8(geminiDir, "settings.json"), `${JSON.stringify(settings, null, 2)}
|
|
7360
7441
|
`, {
|
|
7361
7442
|
encoding: "utf8",
|
|
7362
7443
|
mode: 384
|
|
@@ -7380,10 +7461,10 @@ function prepareGeminiChildEnv(proxyPort, proxyToken) {
|
|
|
7380
7461
|
function launchGemini(geminiPath, modelId, env, extraArgs) {
|
|
7381
7462
|
return new Promise((resolve2) => {
|
|
7382
7463
|
const args = ["-m", modelId, ...extraArgs];
|
|
7383
|
-
const child =
|
|
7464
|
+
const child = spawn4(geminiPath, args, {
|
|
7384
7465
|
stdio: "inherit",
|
|
7385
7466
|
env,
|
|
7386
|
-
shell:
|
|
7467
|
+
shell: isWindows4
|
|
7387
7468
|
});
|
|
7388
7469
|
const onSigInt = () => child.kill("SIGINT");
|
|
7389
7470
|
const onSigTerm = () => child.kill("SIGTERM");
|
|
@@ -10624,27 +10705,27 @@ async function resolveAntigravityLaunchRoutes(opts) {
|
|
|
10624
10705
|
}
|
|
10625
10706
|
|
|
10626
10707
|
// src/antigravity/launch-cli.ts
|
|
10627
|
-
import { execFileSync, execSync as
|
|
10628
|
-
import
|
|
10629
|
-
import { existsSync as
|
|
10630
|
-
import { homedir as
|
|
10631
|
-
import { join as
|
|
10632
|
-
var
|
|
10633
|
-
var
|
|
10634
|
-
|
|
10635
|
-
|
|
10636
|
-
|
|
10708
|
+
import { execFileSync, execSync as execSync4 } from "child_process";
|
|
10709
|
+
import spawn5 from "cross-spawn";
|
|
10710
|
+
import { existsSync as existsSync7 } from "fs";
|
|
10711
|
+
import { homedir as homedir7 } from "os";
|
|
10712
|
+
import { join as join9 } from "path";
|
|
10713
|
+
var isWindows5 = process.platform === "win32";
|
|
10714
|
+
var FALLBACK_PATHS2 = isWindows5 ? [
|
|
10715
|
+
join9(process.env["APPDATA"] ?? homedir7(), "npm", "agy.cmd"),
|
|
10716
|
+
join9(process.env["APPDATA"] ?? homedir7(), "npm", "agy"),
|
|
10717
|
+
join9(homedir7(), "AppData", "Roaming", "npm", "agy.cmd")
|
|
10637
10718
|
] : [
|
|
10638
|
-
|
|
10639
|
-
|
|
10719
|
+
join9(homedir7(), ".local", "bin", "agy"),
|
|
10720
|
+
join9(homedir7(), ".npm", "bin", "agy"),
|
|
10640
10721
|
"/usr/local/bin/agy",
|
|
10641
10722
|
"/opt/homebrew/bin/agy"
|
|
10642
10723
|
];
|
|
10643
10724
|
function findAntigravityCliBinary() {
|
|
10644
10725
|
const override = getAppPathOverride("agy");
|
|
10645
|
-
if (override) return
|
|
10726
|
+
if (override) return existsSync7(override) ? override : null;
|
|
10646
10727
|
try {
|
|
10647
|
-
const result =
|
|
10728
|
+
const result = execSync4(isWindows5 ? "where.exe agy" : "which agy", {
|
|
10648
10729
|
encoding: "utf8",
|
|
10649
10730
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10650
10731
|
});
|
|
@@ -10652,8 +10733,8 @@ function findAntigravityCliBinary() {
|
|
|
10652
10733
|
if (path3) return path3;
|
|
10653
10734
|
} catch {
|
|
10654
10735
|
}
|
|
10655
|
-
for (const path3 of
|
|
10656
|
-
if (
|
|
10736
|
+
for (const path3 of FALLBACK_PATHS2) {
|
|
10737
|
+
if (existsSync7(path3)) return path3;
|
|
10657
10738
|
}
|
|
10658
10739
|
return null;
|
|
10659
10740
|
}
|
|
@@ -10683,7 +10764,7 @@ function launchAntigravityCli(env, extraArgs) {
|
|
|
10683
10764
|
resolve2(127);
|
|
10684
10765
|
return;
|
|
10685
10766
|
}
|
|
10686
|
-
const child =
|
|
10767
|
+
const child = spawn5(binaryPath, extraArgs, {
|
|
10687
10768
|
stdio: "inherit",
|
|
10688
10769
|
env
|
|
10689
10770
|
});
|
|
@@ -10711,10 +10792,10 @@ function launchAntigravityCli(env, extraArgs) {
|
|
|
10711
10792
|
}
|
|
10712
10793
|
|
|
10713
10794
|
// src/antigravity/launch-ide.ts
|
|
10714
|
-
import { execFileSync as execFileSync2, execSync as
|
|
10715
|
-
import { existsSync as
|
|
10716
|
-
import { homedir as
|
|
10717
|
-
import { join as
|
|
10795
|
+
import { execFileSync as execFileSync2, execSync as execSync5, spawn as spawn6 } from "child_process";
|
|
10796
|
+
import { existsSync as existsSync8 } from "fs";
|
|
10797
|
+
import { homedir as homedir8 } from "os";
|
|
10798
|
+
import { join as join10 } from "path";
|
|
10718
10799
|
|
|
10719
10800
|
// src/antigravity/ide-profile.ts
|
|
10720
10801
|
import fs from "fs";
|
|
@@ -10748,8 +10829,8 @@ function prepareIdeProfile(profileDir, gatewayUrl) {
|
|
|
10748
10829
|
}
|
|
10749
10830
|
|
|
10750
10831
|
// src/antigravity/launch-ide.ts
|
|
10751
|
-
var LINUX_APP_PROFILE_DIR =
|
|
10752
|
-
var LINUX_IDE_PROFILE_DIR =
|
|
10832
|
+
var LINUX_APP_PROFILE_DIR = join10(homedir8(), ".relay-ai", "antigravity", "app-profile");
|
|
10833
|
+
var LINUX_IDE_PROFILE_DIR = join10(homedir8(), ".relay-ai", "antigravity", "profile");
|
|
10753
10834
|
function sleep(ms) {
|
|
10754
10835
|
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
10755
10836
|
}
|
|
@@ -10757,10 +10838,10 @@ function linuxAntigravityBinary() {
|
|
|
10757
10838
|
const candidates = [
|
|
10758
10839
|
"/usr/share/antigravity/antigravity",
|
|
10759
10840
|
"/opt/antigravity/antigravity",
|
|
10760
|
-
|
|
10841
|
+
join10(homedir8(), ".local", "share", "antigravity", "antigravity")
|
|
10761
10842
|
];
|
|
10762
10843
|
for (const candidate of candidates) {
|
|
10763
|
-
if (
|
|
10844
|
+
if (existsSync8(candidate)) return candidate;
|
|
10764
10845
|
}
|
|
10765
10846
|
return null;
|
|
10766
10847
|
}
|
|
@@ -10778,7 +10859,7 @@ function linuxKillByProfile(profileDir, signal) {
|
|
|
10778
10859
|
}
|
|
10779
10860
|
}
|
|
10780
10861
|
function runPowerShell(script) {
|
|
10781
|
-
return
|
|
10862
|
+
return execSync5(`powershell.exe -NoProfile -Command ${JSON.stringify(script)}`, {
|
|
10782
10863
|
encoding: "utf8",
|
|
10783
10864
|
stdio: ["pipe", "pipe", "pipe"]
|
|
10784
10865
|
}).trim();
|
|
@@ -10910,34 +10991,34 @@ function quitAntigravityAppGracefully() {
|
|
|
10910
10991
|
}
|
|
10911
10992
|
function findAntigravityAppBinary() {
|
|
10912
10993
|
const override = getAppPathOverride("antigravity");
|
|
10913
|
-
if (override) return
|
|
10994
|
+
if (override) return existsSync8(override) ? override : null;
|
|
10914
10995
|
if (process.platform === "win32") {
|
|
10915
|
-
const localAppData = process.env["LOCALAPPDATA"] ??
|
|
10916
|
-
const winPath =
|
|
10917
|
-
return
|
|
10996
|
+
const localAppData = process.env["LOCALAPPDATA"] ?? join10(homedir8(), "AppData", "Local");
|
|
10997
|
+
const winPath = join10(localAppData, "Programs", "Antigravity", "Antigravity.exe");
|
|
10998
|
+
return existsSync8(winPath) ? winPath : null;
|
|
10918
10999
|
}
|
|
10919
11000
|
if (process.platform === "linux") return linuxAntigravityBinary();
|
|
10920
11001
|
if (process.platform !== "darwin") return null;
|
|
10921
11002
|
const defaultPath = "/Applications/Antigravity.app/Contents/MacOS/Antigravity";
|
|
10922
|
-
if (
|
|
10923
|
-
const homePath =
|
|
10924
|
-
if (
|
|
11003
|
+
if (existsSync8(defaultPath)) return defaultPath;
|
|
11004
|
+
const homePath = join10(homedir8(), "Applications", "Antigravity.app", "Contents", "MacOS", "Antigravity");
|
|
11005
|
+
if (existsSync8(homePath)) return homePath;
|
|
10925
11006
|
return null;
|
|
10926
11007
|
}
|
|
10927
11008
|
function findAntigravityIdeBinary() {
|
|
10928
11009
|
const override = getAppPathOverride("antigravity-ide");
|
|
10929
|
-
if (override) return
|
|
11010
|
+
if (override) return existsSync8(override) ? override : null;
|
|
10930
11011
|
if (process.platform === "win32") {
|
|
10931
|
-
const localAppData = process.env["LOCALAPPDATA"] ??
|
|
10932
|
-
const winPath =
|
|
10933
|
-
return
|
|
11012
|
+
const localAppData = process.env["LOCALAPPDATA"] ?? join10(homedir8(), "AppData", "Local");
|
|
11013
|
+
const winPath = join10(localAppData, "Programs", "Antigravity IDE", "Antigravity IDE.exe");
|
|
11014
|
+
return existsSync8(winPath) ? winPath : null;
|
|
10934
11015
|
}
|
|
10935
11016
|
if (process.platform === "linux") return linuxAntigravityBinary();
|
|
10936
11017
|
if (process.platform !== "darwin") return null;
|
|
10937
11018
|
const defaultPath = "/Applications/Antigravity IDE.app/Contents/Resources/app/bin/antigravity-ide";
|
|
10938
|
-
if (
|
|
10939
|
-
const homePath =
|
|
10940
|
-
if (
|
|
11019
|
+
if (existsSync8(defaultPath)) return defaultPath;
|
|
11020
|
+
const homePath = join10(homedir8(), "Applications", "Antigravity IDE.app", "Contents", "Resources", "app", "bin", "antigravity-ide");
|
|
11021
|
+
if (existsSync8(homePath)) return homePath;
|
|
10941
11022
|
return null;
|
|
10942
11023
|
}
|
|
10943
11024
|
function launchAntigravityApp(env, profileDir, gatewayUrl, extraArgs) {
|
|
@@ -10960,7 +11041,7 @@ function launchAntigravityApp(env, profileDir, gatewayUrl, extraArgs) {
|
|
|
10960
11041
|
`--user-data-dir=${profileDir}`,
|
|
10961
11042
|
...extraArgs
|
|
10962
11043
|
];
|
|
10963
|
-
const child =
|
|
11044
|
+
const child = spawn6(binaryPath, args, {
|
|
10964
11045
|
// GUI app: don't inherit the terminal's stdio (its Electron logs would
|
|
10965
11046
|
// corrupt relay's interactive prompts) and detach into its own process
|
|
10966
11047
|
// group so a Ctrl+C meant for the relay gateway doesn't also kill the app
|
|
@@ -10997,13 +11078,13 @@ function launchAntigravityIde(env, profileDir, gatewayUrl, extraArgs) {
|
|
|
10997
11078
|
return;
|
|
10998
11079
|
}
|
|
10999
11080
|
prepareIdeProfile(profileDir, gatewayUrl);
|
|
11000
|
-
const relayExtensionsDir =
|
|
11081
|
+
const relayExtensionsDir = join10(homedir8(), ".relay-ai", "antigravity", "extensions");
|
|
11001
11082
|
const args = [
|
|
11002
11083
|
`--user-data-dir=${profileDir}`,
|
|
11003
11084
|
`--extensions-dir=${relayExtensionsDir}`,
|
|
11004
11085
|
...extraArgs
|
|
11005
11086
|
];
|
|
11006
|
-
const child =
|
|
11087
|
+
const child = spawn6(binaryPath, args, {
|
|
11007
11088
|
// GUI app: don't inherit the terminal's stdio (its Electron logs would
|
|
11008
11089
|
// corrupt relay's interactive prompts) and detach into its own process
|
|
11009
11090
|
// group so a Ctrl+C meant for the relay gateway doesn't also kill the app
|
|
@@ -11026,8 +11107,8 @@ function launchAntigravityIde(env, profileDir, gatewayUrl, extraArgs) {
|
|
|
11026
11107
|
}
|
|
11027
11108
|
|
|
11028
11109
|
// src/antigravity.ts
|
|
11029
|
-
import { homedir as
|
|
11030
|
-
import { join as
|
|
11110
|
+
import { homedir as homedir9 } from "os";
|
|
11111
|
+
import { join as join11 } from "path";
|
|
11031
11112
|
var SHUTDOWN_DRAIN_MS = 500;
|
|
11032
11113
|
var AGY_FAVORITES_PROVIDER_ID = "__relay_agy_favorites__";
|
|
11033
11114
|
var AGY_FAVORITES_PROVIDER_LABEL = "\u2605 Antigravity CLI Favorites";
|
|
@@ -11321,7 +11402,7 @@ async function runAntigravityAppCommand(childArgs, trace = false, boot) {
|
|
|
11321
11402
|
trace,
|
|
11322
11403
|
boot,
|
|
11323
11404
|
async (env, _routes, gatewayHandle) => {
|
|
11324
|
-
const profileDir =
|
|
11405
|
+
const profileDir = join11(homedir9(), ".relay-ai", "antigravity", "app-profile");
|
|
11325
11406
|
if (isAntigravityAppRunning(profileDir)) {
|
|
11326
11407
|
const restart = await p12.confirm({
|
|
11327
11408
|
message: "Restart Antigravity to apply this Relay gateway?",
|
|
@@ -11369,7 +11450,7 @@ async function runAntigravityIdeCommand(childArgs, trace = false, boot) {
|
|
|
11369
11450
|
trace,
|
|
11370
11451
|
boot,
|
|
11371
11452
|
async (env, _routes, gatewayHandle) => {
|
|
11372
|
-
const profileDir =
|
|
11453
|
+
const profileDir = join11(homedir9(), ".relay-ai", "antigravity", "profile");
|
|
11373
11454
|
if (isAntigravityIdeRunning(profileDir)) {
|
|
11374
11455
|
const restart = await p12.confirm({
|
|
11375
11456
|
message: "Restart Antigravity IDE to apply this Relay gateway?",
|
|
@@ -11414,7 +11495,7 @@ async function runAntigravityIdeCommand(childArgs, trace = false, boot) {
|
|
|
11414
11495
|
// src/codex-app.ts
|
|
11415
11496
|
import pc10 from "picocolors";
|
|
11416
11497
|
import * as p13 from "@clack/prompts";
|
|
11417
|
-
import { join as
|
|
11498
|
+
import { join as join14 } from "path";
|
|
11418
11499
|
|
|
11419
11500
|
// src/codex/app-provider-routes.ts
|
|
11420
11501
|
function codexRouteToProxyRoute(provider, model, apiKey) {
|
|
@@ -11503,14 +11584,14 @@ async function buildCodexAppProviderCatalogRoutes(provider, apiKey, selectedMode
|
|
|
11503
11584
|
}
|
|
11504
11585
|
|
|
11505
11586
|
// src/codex/app-config.ts
|
|
11506
|
-
import { existsSync as
|
|
11507
|
-
import { dirname as dirname2, join as
|
|
11587
|
+
import { existsSync as existsSync9, readFileSync as readFileSync3, rmSync as rmSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
|
|
11588
|
+
import { dirname as dirname2, join as join12 } from "path";
|
|
11508
11589
|
import { parse, stringify } from "smol-toml";
|
|
11509
11590
|
function getCodexConfigPath() {
|
|
11510
|
-
return
|
|
11591
|
+
return join12(getCodexHome(), "config.toml");
|
|
11511
11592
|
}
|
|
11512
11593
|
function getCodexAppSidecarProfilePath() {
|
|
11513
|
-
return
|
|
11594
|
+
return join12(getCodexHome(), `${CODEX_APP_PROVIDER_ID}.config.toml`);
|
|
11514
11595
|
}
|
|
11515
11596
|
function asRecord(value) {
|
|
11516
11597
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -11537,7 +11618,7 @@ function isMultiAgentV2Enabled(value) {
|
|
|
11537
11618
|
return asRecord(value).enabled === true;
|
|
11538
11619
|
}
|
|
11539
11620
|
function readCodexConfigText(path3 = getCodexConfigPath()) {
|
|
11540
|
-
if (!
|
|
11621
|
+
if (!existsSync9(path3)) return "";
|
|
11541
11622
|
return readFileSync3(path3, "utf8");
|
|
11542
11623
|
}
|
|
11543
11624
|
function parseCodexConfig(text6) {
|
|
@@ -11734,13 +11815,13 @@ function restoreConfigFromState(state, configPath = getCodexConfigPath()) {
|
|
|
11734
11815
|
applyRestoreNumber(config, "model_context_window", state.hadModelContextWindow ?? false, state.modelContextWindow);
|
|
11735
11816
|
applyRestoreNumber(config, "model_auto_compact_token_limit", state.hadModelAutoCompactTokenLimit ?? false, state.modelAutoCompactTokenLimit);
|
|
11736
11817
|
const sidecar = getCodexAppSidecarProfilePath();
|
|
11737
|
-
if (
|
|
11818
|
+
if (existsSync9(sidecar)) {
|
|
11738
11819
|
try {
|
|
11739
11820
|
rmSync3(sidecar, { force: true });
|
|
11740
11821
|
} catch {
|
|
11741
11822
|
}
|
|
11742
11823
|
}
|
|
11743
|
-
const hadFile =
|
|
11824
|
+
const hadFile = existsSync9(configPath);
|
|
11744
11825
|
const empty = Object.keys(config).length === 0 || Object.keys(config).length === 1 && "model_providers" in config && Object.keys(asRecord(config.model_providers)).length === 0;
|
|
11745
11826
|
if (!hadFile && empty) return false;
|
|
11746
11827
|
if (empty) {
|
|
@@ -11795,30 +11876,30 @@ async function verifyCodexAppReadiness(spec, options = {}) {
|
|
|
11795
11876
|
// src/codex/app-session.ts
|
|
11796
11877
|
import {
|
|
11797
11878
|
copyFileSync as copyFileSync2,
|
|
11798
|
-
existsSync as
|
|
11879
|
+
existsSync as existsSync10,
|
|
11799
11880
|
mkdirSync as mkdirSync5,
|
|
11800
11881
|
readdirSync as readdirSync2,
|
|
11801
11882
|
readFileSync as readFileSync5,
|
|
11802
11883
|
rmSync as rmSync4,
|
|
11803
11884
|
statSync as statSync2
|
|
11804
11885
|
} from "fs";
|
|
11805
|
-
import { basename as basename2, join as
|
|
11886
|
+
import { basename as basename2, join as join13 } from "path";
|
|
11806
11887
|
import { createHash as createHash4 } from "crypto";
|
|
11807
11888
|
function getAppSessionLockPath(env = process.env) {
|
|
11808
|
-
return
|
|
11889
|
+
return join13(getRelayAiCodexDir(env), "session-app.json");
|
|
11809
11890
|
}
|
|
11810
11891
|
function getAppRestoreStatePath(env = process.env) {
|
|
11811
|
-
return
|
|
11892
|
+
return join13(getRelayAiCodexDir(env), "app-restore-state.json");
|
|
11812
11893
|
}
|
|
11813
11894
|
function getAppCatalogPath(providerId, env = process.env) {
|
|
11814
|
-
return
|
|
11895
|
+
return join13(getRelayAiCodexDir(env), `app-models-${providerId}.json`);
|
|
11815
11896
|
}
|
|
11816
11897
|
function fileSha256(path3) {
|
|
11817
11898
|
return createHash4("sha256").update(readFileSync5(path3)).digest("hex");
|
|
11818
11899
|
}
|
|
11819
11900
|
function readAppSessionLock(env = process.env) {
|
|
11820
11901
|
const path3 = getAppSessionLockPath(env);
|
|
11821
|
-
if (!
|
|
11902
|
+
if (!existsSync10(path3)) return null;
|
|
11822
11903
|
try {
|
|
11823
11904
|
const parsed = JSON.parse(readFileSync5(path3, "utf8"));
|
|
11824
11905
|
if (typeof parsed.pid === "number" && typeof parsed.startedAt === "string") return parsed;
|
|
@@ -11832,11 +11913,11 @@ function writeAppSessionLock(lock, env = process.env) {
|
|
|
11832
11913
|
}
|
|
11833
11914
|
function clearAppSessionLock(env = process.env) {
|
|
11834
11915
|
const path3 = getAppSessionLockPath(env);
|
|
11835
|
-
if (
|
|
11916
|
+
if (existsSync10(path3)) rmSync4(path3, { force: true });
|
|
11836
11917
|
}
|
|
11837
11918
|
function readAppRestoreState(env = process.env) {
|
|
11838
11919
|
const path3 = getAppRestoreStatePath(env);
|
|
11839
|
-
if (!
|
|
11920
|
+
if (!existsSync10(path3)) return null;
|
|
11840
11921
|
try {
|
|
11841
11922
|
return JSON.parse(readFileSync5(path3, "utf8"));
|
|
11842
11923
|
} catch {
|
|
@@ -11850,16 +11931,16 @@ function writeAppRestoreState(state, env = process.env) {
|
|
|
11850
11931
|
}
|
|
11851
11932
|
function clearAppRestoreState(env = process.env) {
|
|
11852
11933
|
const path3 = getAppRestoreStatePath(env);
|
|
11853
|
-
if (
|
|
11934
|
+
if (existsSync10(path3)) rmSync4(path3, { force: true });
|
|
11854
11935
|
}
|
|
11855
11936
|
function backupConfigToml(env = process.env) {
|
|
11856
11937
|
const configPath = getCodexConfigPath();
|
|
11857
|
-
if (!
|
|
11938
|
+
if (!existsSync10(configPath)) return void 0;
|
|
11858
11939
|
rotateBackups(configPath, env);
|
|
11859
11940
|
const backupsDir = getBackupsDir(env);
|
|
11860
11941
|
mkdirSync5(backupsDir, { recursive: true });
|
|
11861
11942
|
const base = basename2(configPath);
|
|
11862
|
-
const backupPath =
|
|
11943
|
+
const backupPath = join13(backupsDir, `${base}.${Date.now()}.bak`);
|
|
11863
11944
|
copyFileSync2(configPath, backupPath);
|
|
11864
11945
|
return backupPath;
|
|
11865
11946
|
}
|
|
@@ -11875,8 +11956,8 @@ function saveAppRestoreStateBeforePatch(env = process.env) {
|
|
|
11875
11956
|
}
|
|
11876
11957
|
function ownedAppCatalogPaths(env = process.env) {
|
|
11877
11958
|
const codexDir = getRelayAiCodexDir(env);
|
|
11878
|
-
if (!
|
|
11879
|
-
return readdirSync2(codexDir).filter((n) => n.startsWith("app-models-") && n.endsWith(".json")).map((n) =>
|
|
11959
|
+
if (!existsSync10(codexDir)) return [];
|
|
11960
|
+
return readdirSync2(codexDir).filter((n) => n.startsWith("app-models-") && n.endsWith(".json")).map((n) => join13(codexDir, n));
|
|
11880
11961
|
}
|
|
11881
11962
|
function removeAppCatalogs(env = process.env) {
|
|
11882
11963
|
const removed = [];
|
|
@@ -11891,10 +11972,10 @@ function removeAppCatalogs(env = process.env) {
|
|
|
11891
11972
|
}
|
|
11892
11973
|
function newestConfigBackup(env = process.env) {
|
|
11893
11974
|
const backupDir = getBackupsDir(env);
|
|
11894
|
-
if (!
|
|
11975
|
+
if (!existsSync10(backupDir)) return null;
|
|
11895
11976
|
const configBase = basename2(getCodexConfigPath());
|
|
11896
11977
|
const candidates = readdirSync2(backupDir).filter((name) => name.startsWith(`${configBase}.`) && name.endsWith(".bak")).map((name) => {
|
|
11897
|
-
const path3 =
|
|
11978
|
+
const path3 = join13(backupDir, name);
|
|
11898
11979
|
try {
|
|
11899
11980
|
return { path: path3, mtimeMs: statSync2(path3).mtimeMs };
|
|
11900
11981
|
} catch {
|
|
@@ -11921,13 +12002,13 @@ function restoreCodexAppOverlay(env = process.env) {
|
|
|
11921
12002
|
return { restored: false, message: "Nothing to restore." };
|
|
11922
12003
|
}
|
|
11923
12004
|
const exactBackupIsSafe = Boolean(
|
|
11924
|
-
managed && lock?.backupPath &&
|
|
12005
|
+
managed && lock?.backupPath && existsSync10(lock.backupPath) && lock.patchedConfigSha256 && lock.originalConfigSha256 && fileSha256(getCodexConfigPath()) === lock.patchedConfigSha256 && fileSha256(lock.backupPath) === lock.originalConfigSha256
|
|
11925
12006
|
);
|
|
11926
12007
|
if (exactBackupIsSafe) {
|
|
11927
12008
|
copyFileSync2(lock.backupPath, getCodexConfigPath());
|
|
11928
12009
|
} else if (restoreState) {
|
|
11929
12010
|
restoreConfigFromState(restoreState);
|
|
11930
|
-
} else if (lock?.backupPath &&
|
|
12011
|
+
} else if (lock?.backupPath && existsSync10(lock.backupPath)) {
|
|
11931
12012
|
copyFileSync2(lock.backupPath, getCodexConfigPath());
|
|
11932
12013
|
} else if (managed) {
|
|
11933
12014
|
const backupPath = newestConfigBackup(env);
|
|
@@ -12505,7 +12586,7 @@ Mixed Codex App mode is unavailable: ${err instanceof Error ? err.message : err}
|
|
|
12505
12586
|
}
|
|
12506
12587
|
};
|
|
12507
12588
|
try {
|
|
12508
|
-
const catalogPath = mixedPlan ?
|
|
12589
|
+
const catalogPath = mixedPlan ? join14(getRelayAiCodexDir(), "app-models-mixed.json") : favoritesActive && resolvedFavorites.length > 0 ? getFavoritesAppCatalogPath() : getAppCatalogPath(route.providerId);
|
|
12509
12590
|
const activeRoute = mixedPlan ? {
|
|
12510
12591
|
tier: "proxy",
|
|
12511
12592
|
modelId: mixedPlan.selectedSlug,
|
|
@@ -12713,31 +12794,31 @@ import pc11 from "picocolors";
|
|
|
12713
12794
|
import * as p14 from "@clack/prompts";
|
|
12714
12795
|
|
|
12715
12796
|
// src/claude-desktop/app-config.ts
|
|
12716
|
-
import { existsSync as
|
|
12717
|
-
import { homedir as
|
|
12718
|
-
import { join as
|
|
12797
|
+
import { existsSync as existsSync11, readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6 } from "fs";
|
|
12798
|
+
import { homedir as homedir10 } from "os";
|
|
12799
|
+
import { join as join15, dirname as dirname3 } from "path";
|
|
12719
12800
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
12720
12801
|
function getClaudeDesktopHome() {
|
|
12721
12802
|
if (process.platform === "win32") {
|
|
12722
|
-
return
|
|
12803
|
+
return join15(process.env.LOCALAPPDATA || join15(homedir10(), "AppData", "Local"), "Claude-3p");
|
|
12723
12804
|
}
|
|
12724
12805
|
if (process.platform === "linux") {
|
|
12725
|
-
return
|
|
12806
|
+
return join15(process.env.XDG_CONFIG_HOME || join15(homedir10(), ".config"), "Claude-3p");
|
|
12726
12807
|
}
|
|
12727
|
-
return
|
|
12808
|
+
return join15(homedir10(), "Library", "Application Support", "Claude-3p");
|
|
12728
12809
|
}
|
|
12729
12810
|
function getConfigLibraryPath() {
|
|
12730
|
-
return
|
|
12811
|
+
return join15(getClaudeDesktopHome(), "configLibrary");
|
|
12731
12812
|
}
|
|
12732
12813
|
function getMetaJsonPath() {
|
|
12733
|
-
return
|
|
12814
|
+
return join15(getConfigLibraryPath(), "_meta.json");
|
|
12734
12815
|
}
|
|
12735
12816
|
function getClaudeDesktopConfigJsonPath() {
|
|
12736
|
-
return
|
|
12817
|
+
return join15(getClaudeDesktopHome(), "claude_desktop_config.json");
|
|
12737
12818
|
}
|
|
12738
12819
|
function readDesktopConfigJson() {
|
|
12739
12820
|
const path3 = getClaudeDesktopConfigJsonPath();
|
|
12740
|
-
if (!
|
|
12821
|
+
if (!existsSync11(path3)) return {};
|
|
12741
12822
|
try {
|
|
12742
12823
|
const parsed = JSON.parse(readFileSync6(path3, "utf8"));
|
|
12743
12824
|
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
|
|
@@ -12771,7 +12852,7 @@ function restoreDeploymentMode(previous) {
|
|
|
12771
12852
|
}
|
|
12772
12853
|
function readMetaJson() {
|
|
12773
12854
|
const metaPath = getMetaJsonPath();
|
|
12774
|
-
if (!
|
|
12855
|
+
if (!existsSync11(metaPath)) return null;
|
|
12775
12856
|
try {
|
|
12776
12857
|
return JSON.parse(readFileSync6(metaPath, "utf8"));
|
|
12777
12858
|
} catch {
|
|
@@ -12795,7 +12876,7 @@ function buildRelayAiConfig(proxyPort) {
|
|
|
12795
12876
|
}
|
|
12796
12877
|
function writeRelayAiConfig(proxyPort) {
|
|
12797
12878
|
const uuid = randomUUID3();
|
|
12798
|
-
const configPath =
|
|
12879
|
+
const configPath = join15(getConfigLibraryPath(), `${uuid}.json`);
|
|
12799
12880
|
const config = buildRelayAiConfig(proxyPort);
|
|
12800
12881
|
mkdirSync6(dirname3(configPath), { recursive: true });
|
|
12801
12882
|
writeFileSync5(configPath, `${JSON.stringify(config, null, 2)}
|
|
@@ -12952,7 +13033,7 @@ async function buildClaudeAppServerCatalog(entries, providersById, trace) {
|
|
|
12952
13033
|
// src/claude-desktop/app-session.ts
|
|
12953
13034
|
import {
|
|
12954
13035
|
copyFileSync as copyFileSync3,
|
|
12955
|
-
existsSync as
|
|
13036
|
+
existsSync as existsSync12,
|
|
12956
13037
|
mkdirSync as mkdirSync7,
|
|
12957
13038
|
readFileSync as readFileSync7,
|
|
12958
13039
|
renameSync as renameSync2,
|
|
@@ -12960,13 +13041,13 @@ import {
|
|
|
12960
13041
|
unlinkSync as unlinkSync2,
|
|
12961
13042
|
writeFileSync as writeFileSync6
|
|
12962
13043
|
} from "fs";
|
|
12963
|
-
import { dirname as dirname4, join as
|
|
13044
|
+
import { dirname as dirname4, join as join16 } from "path";
|
|
12964
13045
|
function getSessionLockPath2() {
|
|
12965
|
-
return
|
|
13046
|
+
return join16(getClaudeDesktopHome(), ".relay-ai.lock");
|
|
12966
13047
|
}
|
|
12967
13048
|
function inspectSessionLock() {
|
|
12968
13049
|
const path3 = getSessionLockPath2();
|
|
12969
|
-
if (!
|
|
13050
|
+
if (!existsSync12(path3)) return { status: "missing" };
|
|
12970
13051
|
try {
|
|
12971
13052
|
const parsed = JSON.parse(readFileSync7(path3, "utf8"));
|
|
12972
13053
|
if (typeof parsed.pid === "number" && typeof parsed.startedAt === "string" && typeof parsed.uuid === "string" && typeof parsed.proxyPort === "number") {
|
|
@@ -13003,14 +13084,14 @@ function isProcessAlive3(pid) {
|
|
|
13003
13084
|
function backupMetaJson() {
|
|
13004
13085
|
const metaPath = getMetaJsonPath();
|
|
13005
13086
|
const backupPath = `${metaPath}.bak`;
|
|
13006
|
-
if (
|
|
13087
|
+
if (existsSync12(metaPath) && !existsSync12(backupPath)) {
|
|
13007
13088
|
copyFileSync3(metaPath, backupPath);
|
|
13008
13089
|
}
|
|
13009
13090
|
}
|
|
13010
13091
|
function restoreMetaJson() {
|
|
13011
13092
|
const metaPath = getMetaJsonPath();
|
|
13012
13093
|
const backupPath = `${metaPath}.bak`;
|
|
13013
|
-
if (
|
|
13094
|
+
if (existsSync12(backupPath)) {
|
|
13014
13095
|
copyFileSync3(backupPath, metaPath);
|
|
13015
13096
|
unlinkSync2(backupPath);
|
|
13016
13097
|
}
|
|
@@ -13027,8 +13108,8 @@ function safeCleanupStep(label, fn) {
|
|
|
13027
13108
|
}
|
|
13028
13109
|
}
|
|
13029
13110
|
function removeRelayAiConfig(uuid) {
|
|
13030
|
-
const configPath =
|
|
13031
|
-
if (
|
|
13111
|
+
const configPath = join16(getConfigLibraryPath(), `${uuid}.json`);
|
|
13112
|
+
if (existsSync12(configPath)) {
|
|
13032
13113
|
try {
|
|
13033
13114
|
rmSync5(configPath, { force: true });
|
|
13034
13115
|
} catch {
|
|
@@ -13110,7 +13191,7 @@ function cleanupSession(uuid) {
|
|
|
13110
13191
|
}
|
|
13111
13192
|
}
|
|
13112
13193
|
const meta = readMetaJson();
|
|
13113
|
-
const configIsReferenced = meta === null ?
|
|
13194
|
+
const configIsReferenced = meta === null ? existsSync12(getMetaJsonPath()) : meta.appliedId === uuid || meta.entries.some((entry) => entry.id === uuid);
|
|
13114
13195
|
if (!sharedStateIsOwnedElsewhere || !configIsReferenced) {
|
|
13115
13196
|
removeRelayAiConfig(uuid);
|
|
13116
13197
|
}
|
|
@@ -13358,17 +13439,17 @@ ${pc11.bold("Claude Desktop 3P Mode Active")}`);
|
|
|
13358
13439
|
}
|
|
13359
13440
|
|
|
13360
13441
|
// src/ai-doc.ts
|
|
13361
|
-
import { existsSync as
|
|
13362
|
-
import { homedir as
|
|
13363
|
-
import { join as
|
|
13442
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
13443
|
+
import { homedir as homedir11 } from "os";
|
|
13444
|
+
import { join as join17 } from "path";
|
|
13364
13445
|
var SKILL_DIR_NAME = "relay-ai-cli";
|
|
13365
13446
|
var SKILL_INSTALL_DIRS = [
|
|
13366
|
-
|
|
13367
|
-
|
|
13368
|
-
|
|
13369
|
-
|
|
13370
|
-
|
|
13371
|
-
|
|
13447
|
+
join17(getAppHome(), "skills"),
|
|
13448
|
+
join17(homedir11(), ".claude", "skills"),
|
|
13449
|
+
join17(homedir11(), ".agents", "skills"),
|
|
13450
|
+
join17(homedir11(), ".codex", "skills"),
|
|
13451
|
+
join17(homedir11(), ".cursor", "skills"),
|
|
13452
|
+
join17(homedir11(), ".cursor", "skills-cursor")
|
|
13372
13453
|
];
|
|
13373
13454
|
function parseSkillVersion(content) {
|
|
13374
13455
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
@@ -13382,8 +13463,8 @@ function parseSkillVersion(content) {
|
|
|
13382
13463
|
return null;
|
|
13383
13464
|
}
|
|
13384
13465
|
function readInstalledSkillVersion(skillDir) {
|
|
13385
|
-
const skillPath =
|
|
13386
|
-
if (!
|
|
13466
|
+
const skillPath = join17(skillDir, "SKILL.md");
|
|
13467
|
+
if (!existsSync13(skillPath)) return null;
|
|
13387
13468
|
try {
|
|
13388
13469
|
const head = readFileSync8(skillPath, "utf-8").slice(0, 1024);
|
|
13389
13470
|
return parseSkillVersion(head.includes("---", 4) ? head : `${head}
|
|
@@ -13395,8 +13476,8 @@ function readInstalledSkillVersion(skillDir) {
|
|
|
13395
13476
|
}
|
|
13396
13477
|
function skillInstallTargets() {
|
|
13397
13478
|
return SKILL_INSTALL_DIRS.map((dir) => {
|
|
13398
|
-
const skillDir =
|
|
13399
|
-
return { skillDir, skillPath:
|
|
13479
|
+
const skillDir = join17(dir, SKILL_DIR_NAME);
|
|
13480
|
+
return { skillDir, skillPath: join17(skillDir, "SKILL.md") };
|
|
13400
13481
|
});
|
|
13401
13482
|
}
|
|
13402
13483
|
function formatProviderModels(provider) {
|
|
@@ -13468,6 +13549,8 @@ relay-ai launches Claude Code, OpenAI Codex, Google Gemini CLI, and desktop apps
|
|
|
13468
13549
|
against YOUR provider registry (Groq, Mistral, OpenAI, Zen/Go, Ollama, custom endpoints, \u2026).
|
|
13469
13550
|
It handles API translation, local proxies, env isolation, and model routing.
|
|
13470
13551
|
|
|
13552
|
+
Binary aliases: relayai and relai run the same CLI (e.g. relai claude --provider groq --model <model-id> -p "<prompt>").
|
|
13553
|
+
|
|
13471
13554
|
SKILL VERSIONING
|
|
13472
13555
|
The installed skill version matches relay-ai --version (currently v${VERSION}).
|
|
13473
13556
|
After upgrading relay-ai, run:
|
|
@@ -14062,7 +14145,7 @@ function buildHttpProxyChildEnv(baseEnv, proxyUrl, caCertPath) {
|
|
|
14062
14145
|
import { randomBytes as randomBytes3, randomUUID as randomUUID4 } from "crypto";
|
|
14063
14146
|
import {
|
|
14064
14147
|
chmodSync as chmodSync3,
|
|
14065
|
-
existsSync as
|
|
14148
|
+
existsSync as existsSync14,
|
|
14066
14149
|
mkdirSync as mkdirSync10,
|
|
14067
14150
|
readFileSync as readFileSync9,
|
|
14068
14151
|
readdirSync as readdirSync3,
|
|
@@ -14070,7 +14153,7 @@ import {
|
|
|
14070
14153
|
statSync as statSync3,
|
|
14071
14154
|
writeFileSync as writeFileSync9
|
|
14072
14155
|
} from "fs";
|
|
14073
|
-
import { dirname as dirname6, join as
|
|
14156
|
+
import { dirname as dirname6, join as join19, resolve } from "path";
|
|
14074
14157
|
import forge from "node-forge";
|
|
14075
14158
|
var SESSION_ROOT = "http-proxy-sessions";
|
|
14076
14159
|
var OWNER_FILE = "owner.pid";
|
|
@@ -14090,16 +14173,16 @@ function processIsRunning(pid) {
|
|
|
14090
14173
|
}
|
|
14091
14174
|
}
|
|
14092
14175
|
function cleanupStaleHttpProxySessions(appHome = getAppHome()) {
|
|
14093
|
-
const root =
|
|
14094
|
-
if (!
|
|
14176
|
+
const root = join19(appHome, SESSION_ROOT);
|
|
14177
|
+
if (!existsSync14(root)) return;
|
|
14095
14178
|
const now = Date.now();
|
|
14096
14179
|
for (const name of readdirSync3(root)) {
|
|
14097
|
-
const sessionDir =
|
|
14180
|
+
const sessionDir = join19(root, name);
|
|
14098
14181
|
try {
|
|
14099
14182
|
const stat = statSync3(sessionDir);
|
|
14100
14183
|
if (!stat.isDirectory()) continue;
|
|
14101
|
-
const ownerPath =
|
|
14102
|
-
if (!
|
|
14184
|
+
const ownerPath = join19(sessionDir, OWNER_FILE);
|
|
14185
|
+
if (!existsSync14(ownerPath)) {
|
|
14103
14186
|
if (now - stat.mtimeMs > MID_CREATION_GRACE_MS) {
|
|
14104
14187
|
rmSync6(sessionDir, { recursive: true, force: true });
|
|
14105
14188
|
}
|
|
@@ -14121,13 +14204,13 @@ function cleanupStaleHttpProxySessions(appHome = getAppHome()) {
|
|
|
14121
14204
|
}
|
|
14122
14205
|
function createHttpProxyCertificates(appHome = getAppHome()) {
|
|
14123
14206
|
cleanupStaleHttpProxySessions(appHome);
|
|
14124
|
-
const root =
|
|
14207
|
+
const root = join19(appHome, SESSION_ROOT);
|
|
14125
14208
|
mkdirSync10(root, { recursive: true, mode: 448 });
|
|
14126
14209
|
chmodSync3(root, 448);
|
|
14127
|
-
const sessionDir =
|
|
14210
|
+
const sessionDir = join19(root, randomUUID4());
|
|
14128
14211
|
mkdirSync10(sessionDir, { mode: 448 });
|
|
14129
14212
|
chmodSync3(sessionDir, 448);
|
|
14130
|
-
writeFileSync9(
|
|
14213
|
+
writeFileSync9(join19(sessionDir, OWNER_FILE), `${process.pid}
|
|
14131
14214
|
`, { mode: 384 });
|
|
14132
14215
|
try {
|
|
14133
14216
|
const caKeys = forge.pki.rsa.generateKeyPair(2048);
|
|
@@ -14162,7 +14245,7 @@ function createHttpProxyCertificates(appHome = getAppHome()) {
|
|
|
14162
14245
|
]);
|
|
14163
14246
|
server.sign(caKeys.privateKey, forge.md.sha256.create());
|
|
14164
14247
|
const caCert = forge.pki.certificateToPem(ca);
|
|
14165
|
-
const caCertPath =
|
|
14248
|
+
const caCertPath = join19(sessionDir, "relay-ai-ca.pem");
|
|
14166
14249
|
writeFileSync9(caCertPath, caCert, { encoding: "utf8", mode: 384 });
|
|
14167
14250
|
chmodSync3(caCertPath, 384);
|
|
14168
14251
|
let cleaned = false;
|
|
@@ -14208,7 +14291,7 @@ function createHttpProxyCaBundle(relayCaCertPath, additionalCaCertPath) {
|
|
|
14208
14291
|
const relayCa = readFileSync9(relayCaCertPath, "utf8").trimEnd();
|
|
14209
14292
|
const additionalCa = readFileSync9(additionalCaCertPath, "utf8").trim();
|
|
14210
14293
|
if (!additionalCa) return relayCaCertPath;
|
|
14211
|
-
const combinedPath =
|
|
14294
|
+
const combinedPath = join19(dirname6(relayCaCertPath), "combined-ca.pem");
|
|
14212
14295
|
writeFileSync9(
|
|
14213
14296
|
combinedPath,
|
|
14214
14297
|
`${relayCa}
|
|
@@ -15240,6 +15323,10 @@ ${pc12.bold("Commands:")}
|
|
|
15240
15323
|
chatgpt Alias for codex-app
|
|
15241
15324
|
claude-app Launch Claude Desktop app with registry providers (macOS + Windows + Linux)
|
|
15242
15325
|
|
|
15326
|
+
${pc12.bold("Binary aliases:")}
|
|
15327
|
+
relayai Same CLI as relay-ai (shorter to type)
|
|
15328
|
+
relai Same CLI as relay-ai (shortest)
|
|
15329
|
+
|
|
15243
15330
|
${pc12.bold("Antigravity favorites:")}
|
|
15244
15331
|
agy, antigravity, and antigravity-ide share up to six Antigravity favorites
|
|
15245
15332
|
from relay-ai favorites --agy, plus the selected launch model.
|
|
@@ -16233,7 +16320,7 @@ Options:
|
|
|
16233
16320
|
--trace Write debug logs under ~/.relay-ai/logs/`);
|
|
16234
16321
|
return 0;
|
|
16235
16322
|
}
|
|
16236
|
-
const { runUiCommand } = await import("./ui-command-
|
|
16323
|
+
const { runUiCommand } = await import("./ui-command-QGVVDO63.js");
|
|
16237
16324
|
return runUiCommand({ trace: parsed.trace, serverMode: parsed.uiServerMode });
|
|
16238
16325
|
}
|
|
16239
16326
|
if (parsed.command === "models") {
|