theclawbay 0.3.63 → 0.3.65
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/commands/setup.js
CHANGED
|
@@ -2986,7 +2986,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
2986
2986
|
let restoredClaudeDesktop3pConfig = false;
|
|
2987
2987
|
let claudeDesktop3pConfigPathManaged = null;
|
|
2988
2988
|
let sessionMigration = null;
|
|
2989
|
-
let
|
|
2989
|
+
let authSeedResult = null;
|
|
2990
2990
|
let stateDbMigration = null;
|
|
2991
2991
|
let modelCacheMigration = null;
|
|
2992
2992
|
let continueConfigPath = null;
|
|
@@ -3088,8 +3088,10 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3088
3088
|
neutralizeSources: HISTORY_PROVIDER_NEUTRALIZE_SOURCES,
|
|
3089
3089
|
});
|
|
3090
3090
|
}
|
|
3091
|
-
|
|
3091
|
+
authSeedResult = await (0, codex_auth_seeding_1.ensureCodexApiKeyAuth)({
|
|
3092
3092
|
codexHome: paths_1.codexDir,
|
|
3093
|
+
apiKey: authCredential,
|
|
3094
|
+
replaceExistingAuth: true,
|
|
3093
3095
|
});
|
|
3094
3096
|
if (migrateCodexConversations) {
|
|
3095
3097
|
stateDbMigration = await (0, codex_history_migration_1.migrateStateDbProviders)({
|
|
@@ -3229,13 +3231,11 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3229
3231
|
}
|
|
3230
3232
|
if (modelCacheMigration?.warning)
|
|
3231
3233
|
summaryNotes.add(modelCacheMigration.warning);
|
|
3232
|
-
if (
|
|
3233
|
-
summaryNotes.add(
|
|
3234
|
-
if (
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
else if (authSeedCleanup?.action === "restored_backup") {
|
|
3238
|
-
summaryNotes.add("Restored the Codex auth that existed before an older The Claw Bay auth override.");
|
|
3234
|
+
if (authSeedResult?.warning)
|
|
3235
|
+
summaryNotes.add(authSeedResult.warning);
|
|
3236
|
+
if (authSeedResult &&
|
|
3237
|
+
["seeded", "updated", "already_seeded"].includes(authSeedResult.action)) {
|
|
3238
|
+
summaryNotes.add("Codex desktop clients were pinned to local API-key auth so current VS Code and Codex app builds keep the The Claw Bay model picker instead of falling back to OpenAI's default model catalog.");
|
|
3239
3239
|
}
|
|
3240
3240
|
if (selectedSetupClients.has("codex") && !migrateCodexConversations) {
|
|
3241
3241
|
summaryNotes.add("Left existing Codex conversations untouched.");
|
|
@@ -3338,17 +3338,22 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3338
3338
|
else if (modelCacheMigration) {
|
|
3339
3339
|
this.log("- Codex model cache: no change.");
|
|
3340
3340
|
}
|
|
3341
|
-
if (
|
|
3342
|
-
this.log(
|
|
3341
|
+
if (authSeedResult?.action === "seeded") {
|
|
3342
|
+
this.log(authSeedResult.replacedExistingAuth
|
|
3343
|
+
? "- Codex login state: backed up the existing Codex auth and switched local desktop auth to The Claw Bay API-key mode."
|
|
3344
|
+
: "- Codex login state: seeded local desktop auth in The Claw Bay API-key mode.");
|
|
3345
|
+
}
|
|
3346
|
+
else if (authSeedResult?.action === "updated") {
|
|
3347
|
+
this.log("- Codex login state: refreshed the local The Claw Bay API-key auth seed.");
|
|
3343
3348
|
}
|
|
3344
|
-
else if (
|
|
3345
|
-
this.log("- Codex login state:
|
|
3349
|
+
else if (authSeedResult?.action === "already_seeded") {
|
|
3350
|
+
this.log("- Codex login state: local desktop auth was already pinned to The Claw Bay API-key mode.");
|
|
3346
3351
|
}
|
|
3347
|
-
else if (
|
|
3348
|
-
this.log(`- Codex login state: ${
|
|
3352
|
+
else if (authSeedResult?.warning) {
|
|
3353
|
+
this.log(`- Codex login state: ${authSeedResult.warning}`);
|
|
3349
3354
|
}
|
|
3350
3355
|
else {
|
|
3351
|
-
this.log("- Codex login state:
|
|
3356
|
+
this.log("- Codex login state: no change.");
|
|
3352
3357
|
}
|
|
3353
3358
|
}
|
|
3354
3359
|
else if (codexDetected) {
|
|
@@ -12,10 +12,12 @@ export type CleanupCodexAuthResult = {
|
|
|
12
12
|
export declare function ensureCodexApiKeyAuth(params: {
|
|
13
13
|
codexHome: string;
|
|
14
14
|
apiKey: string;
|
|
15
|
+
replaceExistingAuth?: boolean;
|
|
15
16
|
}): Promise<EnsureCodexAuthResult>;
|
|
16
17
|
export declare function ensureCodexUsageLimitAuth(params: {
|
|
17
18
|
codexHome: string;
|
|
18
19
|
apiKey: string;
|
|
20
|
+
replaceExistingAuth?: boolean;
|
|
19
21
|
}): Promise<EnsureCodexAuthResult>;
|
|
20
22
|
export declare function cleanupSeededCodexAuth(params: {
|
|
21
23
|
codexHome: string;
|
|
@@ -236,7 +236,7 @@ async function ensureCodexApiKeyAuth(params) {
|
|
|
236
236
|
codexHome: params.codexHome,
|
|
237
237
|
apiKey: params.apiKey,
|
|
238
238
|
mode: "api-key",
|
|
239
|
-
replaceExistingAuth: false,
|
|
239
|
+
replaceExistingAuth: params.replaceExistingAuth ?? false,
|
|
240
240
|
});
|
|
241
241
|
}
|
|
242
242
|
async function ensureCodexUsageLimitAuth(params) {
|
|
@@ -39,6 +39,7 @@ const FALLBACK_BASE_INSTRUCTIONS = `You are Codex, a coding agent based on GPT-5
|
|
|
39
39
|
- Prefer rg or rg --files for search when available.
|
|
40
40
|
- Make safe, minimal code changes that preserve user work.
|
|
41
41
|
- Explain what changed and any remaining risk clearly.`;
|
|
42
|
+
const SEEDED_CACHE_FRESHNESS_YEARS = 10;
|
|
42
43
|
function objectRecordOr(value) {
|
|
43
44
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
44
45
|
return value;
|
|
@@ -239,11 +240,25 @@ function buildSeedModel(models, modelId) {
|
|
|
239
240
|
}
|
|
240
241
|
return normalizeSeedModel(null, modelId);
|
|
241
242
|
}
|
|
243
|
+
function hasSeededTheClawBayModel(models) {
|
|
244
|
+
return models.some((model) => hasSeedMarker(model));
|
|
245
|
+
}
|
|
246
|
+
function nextFetchedAtIsoForDocument(doc) {
|
|
247
|
+
if (!hasSeededTheClawBayModel(doc.models)) {
|
|
248
|
+
return new Date().toISOString();
|
|
249
|
+
}
|
|
250
|
+
// Current desktop Codex builds only consult models_cache.json for custom-provider
|
|
251
|
+
// catalogs in API-key mode, then silently fall back to compiled OpenAI models once
|
|
252
|
+
// the five-minute TTL expires. Keep the seeded cache durable until setup refreshes it.
|
|
253
|
+
const next = new Date();
|
|
254
|
+
next.setUTCFullYear(next.getUTCFullYear() + SEEDED_CACHE_FRESHNESS_YEARS);
|
|
255
|
+
return next.toISOString();
|
|
256
|
+
}
|
|
242
257
|
function setCacheFreshnessMetadata(doc, clientVersion) {
|
|
243
258
|
let changed = false;
|
|
244
|
-
const
|
|
245
|
-
if (doc.fetched_at !==
|
|
246
|
-
doc.fetched_at =
|
|
259
|
+
const fetchedAt = nextFetchedAtIsoForDocument(doc);
|
|
260
|
+
if (doc.fetched_at !== fetchedAt) {
|
|
261
|
+
doc.fetched_at = fetchedAt;
|
|
247
262
|
changed = true;
|
|
248
263
|
}
|
|
249
264
|
if (clientVersion && doc.client_version !== clientVersion) {
|
|
@@ -265,6 +280,159 @@ function runVersionCommand(command, args) {
|
|
|
265
280
|
return null;
|
|
266
281
|
return parseCodexVersion(`${run.stdout ?? ""}\n${run.stderr ?? ""}`);
|
|
267
282
|
}
|
|
283
|
+
function compareCodexVersions(left, right) {
|
|
284
|
+
const leftParts = left.split(".").map((part) => Number.parseInt(part, 10));
|
|
285
|
+
const rightParts = right.split(".").map((part) => Number.parseInt(part, 10));
|
|
286
|
+
const maxLen = Math.max(leftParts.length, rightParts.length);
|
|
287
|
+
for (let index = 0; index < maxLen; index += 1) {
|
|
288
|
+
const leftPart = leftParts[index] ?? 0;
|
|
289
|
+
const rightPart = rightParts[index] ?? 0;
|
|
290
|
+
if (leftPart !== rightPart)
|
|
291
|
+
return leftPart - rightPart;
|
|
292
|
+
}
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
function highestCodexVersion(candidates) {
|
|
296
|
+
const versions = candidates
|
|
297
|
+
.map((candidate) => (candidate ? parseCodexVersion(candidate) : null))
|
|
298
|
+
.filter((candidate) => Boolean(candidate));
|
|
299
|
+
if (versions.length === 0)
|
|
300
|
+
return null;
|
|
301
|
+
versions.sort((left, right) => compareCodexVersions(right, left));
|
|
302
|
+
return versions[0] ?? null;
|
|
303
|
+
}
|
|
304
|
+
function uniqueStrings(values) {
|
|
305
|
+
return Array.from(new Set(values.filter(Boolean)));
|
|
306
|
+
}
|
|
307
|
+
function isWslInteropRuntime() {
|
|
308
|
+
return node_os_1.default.platform() === "linux" && Boolean(process.env.WSL_DISTRO_NAME || process.env.WSL_INTEROP);
|
|
309
|
+
}
|
|
310
|
+
function readWindowsCommandStdout(command) {
|
|
311
|
+
const shell = node_os_1.default.platform() === "win32" ? "powershell.exe" : isWslInteropRuntime() ? "powershell.exe" : null;
|
|
312
|
+
if (!shell)
|
|
313
|
+
return null;
|
|
314
|
+
const result = (0, node_child_process_1.spawnSync)(shell, ["-NoProfile", "-Command", command], {
|
|
315
|
+
encoding: "utf8",
|
|
316
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
317
|
+
});
|
|
318
|
+
if (result.status !== 0)
|
|
319
|
+
return null;
|
|
320
|
+
const next = result.stdout.replace(/\r/g, "").trim();
|
|
321
|
+
return next ? next : null;
|
|
322
|
+
}
|
|
323
|
+
function resolveWindowsPathForHost(input) {
|
|
324
|
+
if (!input)
|
|
325
|
+
return null;
|
|
326
|
+
const trimmed = input.trim();
|
|
327
|
+
if (!trimmed)
|
|
328
|
+
return null;
|
|
329
|
+
if (node_os_1.default.platform() === "win32")
|
|
330
|
+
return trimmed;
|
|
331
|
+
const match = /^([A-Za-z]):\\(.*)$/.exec(trimmed);
|
|
332
|
+
if (!match)
|
|
333
|
+
return null;
|
|
334
|
+
const drive = match[1].toLowerCase();
|
|
335
|
+
const rest = match[2].replace(/\\/g, "/");
|
|
336
|
+
return node_path_1.default.posix.join("/mnt", drive, rest);
|
|
337
|
+
}
|
|
338
|
+
function resolveWindowsHomeDirForHost() {
|
|
339
|
+
const reported = readWindowsCommandStdout("$env:USERPROFILE");
|
|
340
|
+
if (reported)
|
|
341
|
+
return resolveWindowsPathForHost(reported);
|
|
342
|
+
if (node_os_1.default.platform() === "win32")
|
|
343
|
+
return node_os_1.default.homedir();
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
function editorExtensionDirCandidates() {
|
|
347
|
+
const home = node_os_1.default.homedir();
|
|
348
|
+
const dirs = [];
|
|
349
|
+
if (node_os_1.default.platform() === "darwin") {
|
|
350
|
+
dirs.push(node_path_1.default.join(home, ".vscode", "extensions"), node_path_1.default.join(home, ".vscode-insiders", "extensions"), node_path_1.default.join(home, ".cursor", "extensions"), node_path_1.default.join(home, ".windsurf", "extensions"), node_path_1.default.join(home, ".vscode-oss", "extensions"));
|
|
351
|
+
return uniqueStrings(dirs);
|
|
352
|
+
}
|
|
353
|
+
if (node_os_1.default.platform() === "win32") {
|
|
354
|
+
const homeDir = process.env.USERPROFILE?.trim() || home;
|
|
355
|
+
dirs.push(node_path_1.default.join(homeDir, ".vscode", "extensions"), node_path_1.default.join(homeDir, ".vscode-insiders", "extensions"), node_path_1.default.join(homeDir, ".cursor", "extensions"), node_path_1.default.join(homeDir, ".windsurf", "extensions"), node_path_1.default.join(homeDir, ".vscode-oss", "extensions"));
|
|
356
|
+
return uniqueStrings(dirs);
|
|
357
|
+
}
|
|
358
|
+
dirs.push(node_path_1.default.join(home, ".vscode", "extensions"), node_path_1.default.join(home, ".vscode-insiders", "extensions"), node_path_1.default.join(home, ".cursor", "extensions"), node_path_1.default.join(home, ".windsurf", "extensions"), node_path_1.default.join(home, ".vscode-oss", "extensions"));
|
|
359
|
+
if (isWslInteropRuntime()) {
|
|
360
|
+
const windowsHome = resolveWindowsHomeDirForHost();
|
|
361
|
+
if (windowsHome) {
|
|
362
|
+
dirs.push(node_path_1.default.join(windowsHome, ".vscode", "extensions"), node_path_1.default.join(windowsHome, ".vscode-insiders", "extensions"), node_path_1.default.join(windowsHome, ".cursor", "extensions"), node_path_1.default.join(windowsHome, ".windsurf", "extensions"), node_path_1.default.join(windowsHome, ".vscode-oss", "extensions"));
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
return uniqueStrings(dirs);
|
|
366
|
+
}
|
|
367
|
+
async function pathExists(filePath) {
|
|
368
|
+
try {
|
|
369
|
+
await promises_1.default.access(filePath);
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
function codexBinaryCandidatesForBinRoot(binRoot) {
|
|
377
|
+
const runtimePreferred = node_os_1.default.platform() === "win32"
|
|
378
|
+
? [
|
|
379
|
+
node_path_1.default.join(binRoot, "windows-x86_64", "codex.exe"),
|
|
380
|
+
node_path_1.default.join(binRoot, "windows-arm64", "codex.exe"),
|
|
381
|
+
]
|
|
382
|
+
: node_os_1.default.platform() === "darwin"
|
|
383
|
+
? [
|
|
384
|
+
node_path_1.default.join(binRoot, "darwin-aarch64", "codex"),
|
|
385
|
+
node_path_1.default.join(binRoot, "darwin-arm64", "codex"),
|
|
386
|
+
node_path_1.default.join(binRoot, "darwin-x86_64", "codex"),
|
|
387
|
+
]
|
|
388
|
+
: [
|
|
389
|
+
node_path_1.default.join(binRoot, "linux-x86_64", "codex"),
|
|
390
|
+
node_path_1.default.join(binRoot, "linux-arm64", "codex"),
|
|
391
|
+
];
|
|
392
|
+
return uniqueStrings([
|
|
393
|
+
...runtimePreferred,
|
|
394
|
+
node_path_1.default.join(binRoot, "codex"),
|
|
395
|
+
node_path_1.default.join(binRoot, "codex.exe"),
|
|
396
|
+
]);
|
|
397
|
+
}
|
|
398
|
+
async function inferCodexClientVersionsFromInstalledExtensions() {
|
|
399
|
+
const versions = new Set();
|
|
400
|
+
for (const extensionDir of editorExtensionDirCandidates()) {
|
|
401
|
+
let entries = [];
|
|
402
|
+
try {
|
|
403
|
+
entries = await promises_1.default.readdir(extensionDir, { withFileTypes: true });
|
|
404
|
+
}
|
|
405
|
+
catch (error) {
|
|
406
|
+
const err = error;
|
|
407
|
+
if (err.code === "ENOENT")
|
|
408
|
+
continue;
|
|
409
|
+
throw error;
|
|
410
|
+
}
|
|
411
|
+
for (const entry of entries) {
|
|
412
|
+
if (!entry.isDirectory())
|
|
413
|
+
continue;
|
|
414
|
+
if (!entry.name.toLowerCase().startsWith("openai.chatgpt-"))
|
|
415
|
+
continue;
|
|
416
|
+
const binRoot = node_path_1.default.join(extensionDir, entry.name, "bin");
|
|
417
|
+
for (const candidate of codexBinaryCandidatesForBinRoot(binRoot)) {
|
|
418
|
+
if (!(await pathExists(candidate)))
|
|
419
|
+
continue;
|
|
420
|
+
const parsed = runVersionCommand(candidate, ["--version"]);
|
|
421
|
+
if (parsed)
|
|
422
|
+
versions.add(parsed);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return [...versions];
|
|
427
|
+
}
|
|
428
|
+
async function inferCodexClientVersionFromVersionJson(codexHome) {
|
|
429
|
+
const parsed = await readJsonIfExists(node_path_1.default.join(codexHome, "version.json"));
|
|
430
|
+
const obj = objectRecordOr(parsed);
|
|
431
|
+
if (!obj)
|
|
432
|
+
return null;
|
|
433
|
+
const latestVersion = typeof obj.latest_version === "string" ? obj.latest_version : "";
|
|
434
|
+
return latestVersion ? parseCodexVersion(latestVersion) : null;
|
|
435
|
+
}
|
|
268
436
|
function resolvePythonCommand() {
|
|
269
437
|
const candidates = [
|
|
270
438
|
{ command: "python3", args: ["-c", "import sqlite3"] },
|
|
@@ -355,20 +523,29 @@ async function inferCodexClientVersionFromStateDb(codexHome) {
|
|
|
355
523
|
return null;
|
|
356
524
|
}
|
|
357
525
|
async function inferCodexClientVersion(codexHome) {
|
|
526
|
+
const versions = [];
|
|
358
527
|
if (node_os_1.default.platform() === "win32") {
|
|
359
528
|
for (const commandLine of ["codex --version", "codex-cli --version", "codex.cmd --version", "codex-cli.cmd --version"]) {
|
|
360
529
|
const parsed = runVersionCommand("cmd.exe", ["/d", "/s", "/c", commandLine]);
|
|
361
530
|
if (parsed)
|
|
362
|
-
|
|
531
|
+
versions.push(parsed);
|
|
363
532
|
}
|
|
364
|
-
return await inferCodexClientVersionFromStateDb(codexHome);
|
|
365
533
|
}
|
|
366
|
-
|
|
367
|
-
const
|
|
368
|
-
|
|
369
|
-
|
|
534
|
+
else {
|
|
535
|
+
for (const command of ["codex", "codex-cli"]) {
|
|
536
|
+
const parsed = runVersionCommand(command, ["--version"]);
|
|
537
|
+
if (parsed)
|
|
538
|
+
versions.push(parsed);
|
|
539
|
+
}
|
|
370
540
|
}
|
|
371
|
-
|
|
541
|
+
versions.push(...await inferCodexClientVersionsFromInstalledExtensions());
|
|
542
|
+
const versionJsonVersion = await inferCodexClientVersionFromVersionJson(codexHome);
|
|
543
|
+
if (versionJsonVersion)
|
|
544
|
+
versions.push(versionJsonVersion);
|
|
545
|
+
const stateDbVersion = await inferCodexClientVersionFromStateDb(codexHome);
|
|
546
|
+
if (stateDbVersion)
|
|
547
|
+
versions.push(stateDbVersion);
|
|
548
|
+
return highestCodexVersion(versions);
|
|
372
549
|
}
|
|
373
550
|
function normalizeCacheDocument(value) {
|
|
374
551
|
const doc = objectRecordOr(value);
|
|
@@ -402,7 +579,7 @@ async function ensureCodexModelCacheHasGpt54(params) {
|
|
|
402
579
|
nextState[modelId] = fingerprintModel(seed);
|
|
403
580
|
}
|
|
404
581
|
const doc = {
|
|
405
|
-
fetched_at:
|
|
582
|
+
fetched_at: nextFetchedAtIsoForDocument({ models: docModels }),
|
|
406
583
|
client_version: clientVersion,
|
|
407
584
|
models: docModels,
|
|
408
585
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theclawbay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.65",
|
|
4
4
|
"description": "CLI for connecting Codex, Continue, Cline, GSD, OpenClaw, OpenCode, Kilo, Roo Code, Aider, experimental Trae, and experimental Zo to The Claw Bay.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|