theclawbay 0.3.79 → 0.3.81
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 +118 -15
- package/dist/lib/backups.js +23 -8
- package/package.json +1 -1
package/dist/commands/setup.js
CHANGED
|
@@ -672,6 +672,54 @@ function shellQuote(value) {
|
|
|
672
672
|
function powerShellQuote(value) {
|
|
673
673
|
return `'${value.replace(/'/g, "''")}'`;
|
|
674
674
|
}
|
|
675
|
+
function shellCommandForCurrentPlatform(command) {
|
|
676
|
+
if (node_os_1.default.platform() === "win32") {
|
|
677
|
+
return { executable: "cmd.exe", args: ["/c", command] };
|
|
678
|
+
}
|
|
679
|
+
return { executable: "bash", args: ["-lc", command] };
|
|
680
|
+
}
|
|
681
|
+
function installPlanForSetupClient(clientId) {
|
|
682
|
+
if (clientId === "codex") {
|
|
683
|
+
return {
|
|
684
|
+
summary: "Install Codex CLI",
|
|
685
|
+
command: "npm install -g @openai/codex",
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
if (clientId === "claude") {
|
|
689
|
+
return {
|
|
690
|
+
summary: "Install Claude Code CLI",
|
|
691
|
+
command: "npm install -g @anthropic-ai/claude-code",
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
if (clientId === "opencode") {
|
|
695
|
+
return {
|
|
696
|
+
summary: "Install OpenCode CLI",
|
|
697
|
+
command: "npm install -g opencode-ai",
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
if (clientId === "aider") {
|
|
701
|
+
return {
|
|
702
|
+
summary: "Install Aider",
|
|
703
|
+
command: node_os_1.default.platform() === "win32"
|
|
704
|
+
? "py -m pip install --user --upgrade aider-chat"
|
|
705
|
+
: "python3 -m pip install --user --upgrade aider-chat",
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
return null;
|
|
709
|
+
}
|
|
710
|
+
function isSetupClientInstallable(clientId) {
|
|
711
|
+
return installPlanForSetupClient(clientId) !== null;
|
|
712
|
+
}
|
|
713
|
+
function runInstallPlan(plan) {
|
|
714
|
+
const { executable, args } = shellCommandForCurrentPlatform(plan.command);
|
|
715
|
+
const run = (0, node_child_process_1.spawnSync)(executable, args, {
|
|
716
|
+
stdio: "inherit",
|
|
717
|
+
env: process.env,
|
|
718
|
+
});
|
|
719
|
+
if (run.status === 0)
|
|
720
|
+
return;
|
|
721
|
+
throw new Error(`${plan.summary} failed.`);
|
|
722
|
+
}
|
|
675
723
|
function modelDisplayName(modelId) {
|
|
676
724
|
return MODEL_DISPLAY_NAMES[modelId] ?? prettyModelId(modelId);
|
|
677
725
|
}
|
|
@@ -1149,17 +1197,18 @@ async function promptForSetupClients(clients) {
|
|
|
1149
1197
|
stdout.write(`${paint("Move to Apply setup and press Enter when you're ready.", ansi.dim, ansi.gray)}\n\n`);
|
|
1150
1198
|
for (const [index, option] of options.entries()) {
|
|
1151
1199
|
const pointer = index === cursor ? paint(">", ansi.bold) : " ";
|
|
1152
|
-
const
|
|
1200
|
+
const selectable = option.detected || option.installable;
|
|
1201
|
+
const mark = selectable
|
|
1153
1202
|
? option.checked
|
|
1154
1203
|
? paint("[x]", ansi.green, ansi.bold)
|
|
1155
1204
|
: paint("[ ]", ansi.gray)
|
|
1156
1205
|
: paint("[-]", ansi.red, ansi.bold);
|
|
1157
1206
|
const badge = option.detected
|
|
1158
|
-
?
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
const label =
|
|
1207
|
+
? paint("found", ansi.green)
|
|
1208
|
+
: option.installable
|
|
1209
|
+
? paint(option.checked ? "will install" : "available to install", ansi.yellow)
|
|
1210
|
+
: paint("not found", ansi.red);
|
|
1211
|
+
const label = selectable
|
|
1163
1212
|
? formatSetupClientLabel(option, hyperlinksEnabled)
|
|
1164
1213
|
: paint(formatSetupClientLabel(option, hyperlinksEnabled), ansi.dim, ansi.gray);
|
|
1165
1214
|
stdout.write(`${pointer} ${index + 1}. ${mark} ${label} ${badge}\n`);
|
|
@@ -1189,13 +1238,18 @@ async function promptForSetupClients(clients) {
|
|
|
1189
1238
|
if (!option)
|
|
1190
1239
|
return;
|
|
1191
1240
|
cursor = index;
|
|
1192
|
-
if (!option.detected) {
|
|
1241
|
+
if (!option.detected && !option.installable) {
|
|
1193
1242
|
hint = `${option.label} is not detected on this machine yet, so it cannot be selected.`;
|
|
1194
1243
|
render();
|
|
1195
1244
|
return;
|
|
1196
1245
|
}
|
|
1197
1246
|
option.checked = !option.checked;
|
|
1198
|
-
|
|
1247
|
+
if (option.checked && !option.detected && option.installable) {
|
|
1248
|
+
hint = `${option.label} selected. Setup will install it first.`;
|
|
1249
|
+
}
|
|
1250
|
+
else {
|
|
1251
|
+
hint = `${option.label} ${option.checked ? "selected" : "cleared"}.`;
|
|
1252
|
+
}
|
|
1199
1253
|
render();
|
|
1200
1254
|
};
|
|
1201
1255
|
const onKeypress = (_str, key) => {
|
|
@@ -1252,6 +1306,7 @@ async function promptForSetupClients(clients) {
|
|
|
1252
1306
|
}
|
|
1253
1307
|
};
|
|
1254
1308
|
(0, node_readline_1.emitKeypressEvents)(stdin);
|
|
1309
|
+
stdin.resume();
|
|
1255
1310
|
if (stdin.isTTY)
|
|
1256
1311
|
stdin.setRawMode(true);
|
|
1257
1312
|
stdout.write("\x1b[?25l");
|
|
@@ -1265,7 +1320,7 @@ function resolveSetupClientSelection(params) {
|
|
|
1265
1320
|
for (const client of setupClients) {
|
|
1266
1321
|
if (!flagSelection.has(client.id))
|
|
1267
1322
|
continue;
|
|
1268
|
-
if (!client.detected) {
|
|
1323
|
+
if (!client.detected && !client.installable) {
|
|
1269
1324
|
throw new Error(`${client.label} is not detected on this machine, so it cannot be selected yet.`);
|
|
1270
1325
|
}
|
|
1271
1326
|
}
|
|
@@ -1276,6 +1331,20 @@ function resolveSetupClientSelection(params) {
|
|
|
1276
1331
|
return Promise.resolve(defaults);
|
|
1277
1332
|
return promptForSetupClients(setupClients);
|
|
1278
1333
|
}
|
|
1334
|
+
function installSelectedMissingClients(params) {
|
|
1335
|
+
const installed = [];
|
|
1336
|
+
for (const client of params.setupClients) {
|
|
1337
|
+
if (!params.selectedClientIds.has(client.id) || client.detected || !client.installable)
|
|
1338
|
+
continue;
|
|
1339
|
+
const plan = installPlanForSetupClient(client.id);
|
|
1340
|
+
if (!plan)
|
|
1341
|
+
continue;
|
|
1342
|
+
params.log(`Installing ${client.summaryLabel}...`);
|
|
1343
|
+
runInstallPlan(plan);
|
|
1344
|
+
installed.push(client.summaryLabel);
|
|
1345
|
+
}
|
|
1346
|
+
return installed;
|
|
1347
|
+
}
|
|
1279
1348
|
async function promptForCodexConversationMigration() {
|
|
1280
1349
|
if (!process.stdin.isTTY || !process.stdout.isTTY)
|
|
1281
1350
|
return false;
|
|
@@ -1290,6 +1359,7 @@ async function promptForCodexConversationMigration() {
|
|
|
1290
1359
|
}
|
|
1291
1360
|
finally {
|
|
1292
1361
|
rl.close();
|
|
1362
|
+
process.stdin.resume();
|
|
1293
1363
|
}
|
|
1294
1364
|
}
|
|
1295
1365
|
async function resolveCodexConversationMigrationSelection(params) {
|
|
@@ -1319,6 +1389,7 @@ async function resolveDeviceLabel(params) {
|
|
|
1319
1389
|
}
|
|
1320
1390
|
finally {
|
|
1321
1391
|
rl.close();
|
|
1392
|
+
process.stdin.resume();
|
|
1322
1393
|
}
|
|
1323
1394
|
}
|
|
1324
1395
|
async function promptForGroupedModelSelection(params) {
|
|
@@ -1480,6 +1551,7 @@ async function promptForGroupedModelSelection(params) {
|
|
|
1480
1551
|
resolvePromise = resolve;
|
|
1481
1552
|
});
|
|
1482
1553
|
(0, node_readline_1.emitKeypressEvents)(stdin);
|
|
1554
|
+
stdin.resume();
|
|
1483
1555
|
if (stdin.isTTY)
|
|
1484
1556
|
stdin.setRawMode(true);
|
|
1485
1557
|
stdout.write("\x1b[?25l");
|
|
@@ -1562,6 +1634,7 @@ async function promptForPrimaryModel(models, defaultModel) {
|
|
|
1562
1634
|
resolvePromise = resolve;
|
|
1563
1635
|
});
|
|
1564
1636
|
(0, node_readline_1.emitKeypressEvents)(stdin);
|
|
1637
|
+
stdin.resume();
|
|
1565
1638
|
if (stdin.isTTY)
|
|
1566
1639
|
stdin.setRawMode(true);
|
|
1567
1640
|
stdout.write("\x1b[?25l");
|
|
@@ -1950,7 +2023,7 @@ function isOpenAiCompatibleSetupModelId(modelId) {
|
|
|
1950
2023
|
const trimmed = modelId.trim();
|
|
1951
2024
|
if (!trimmed)
|
|
1952
2025
|
return false;
|
|
1953
|
-
return !trimmed.startsWith("claude-");
|
|
2026
|
+
return !trimmed.startsWith("claude-") && SUPPORTED_MODEL_IDS.includes(trimmed);
|
|
1954
2027
|
}
|
|
1955
2028
|
function formatDotEnvValue(value) {
|
|
1956
2029
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
@@ -2033,7 +2106,7 @@ async function writeHermesConfig(params) {
|
|
|
2033
2106
|
}
|
|
2034
2107
|
async function resolveModels(backendUrl, apiKey) {
|
|
2035
2108
|
const { ids, failure } = await fetchBackendModelIds(backendUrl, apiKey);
|
|
2036
|
-
const filteredIds = (ids ?? []).filter(isOpenAiCompatibleSetupModelId);
|
|
2109
|
+
const filteredIds = uniqueStrings((ids ?? []).filter(isOpenAiCompatibleSetupModelId));
|
|
2037
2110
|
const available = new Set(filteredIds);
|
|
2038
2111
|
let selected = DEFAULT_CODEX_MODEL;
|
|
2039
2112
|
let note;
|
|
@@ -2060,10 +2133,14 @@ async function resolveModels(backendUrl, apiKey) {
|
|
|
2060
2133
|
unique.push(modelId);
|
|
2061
2134
|
};
|
|
2062
2135
|
pushUnique(selected);
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2136
|
+
if (filteredIds.length > 0) {
|
|
2137
|
+
for (const modelId of filteredIds)
|
|
2138
|
+
pushUnique(modelId);
|
|
2139
|
+
}
|
|
2140
|
+
else {
|
|
2141
|
+
for (const modelId of DEFAULT_MODELS)
|
|
2142
|
+
pushUnique(modelId);
|
|
2143
|
+
}
|
|
2067
2144
|
return {
|
|
2068
2145
|
model: selected,
|
|
2069
2146
|
models: unique.map((modelId) => ({ id: modelId, name: modelDisplayName(modelId) || prettyModelId(modelId) })),
|
|
@@ -3485,6 +3562,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3485
3562
|
summaryLabel: "Codex",
|
|
3486
3563
|
detected: codexDetected,
|
|
3487
3564
|
recommended: true,
|
|
3565
|
+
installable: true,
|
|
3488
3566
|
icon: "◎",
|
|
3489
3567
|
siteUrl: "https://openai.com/codex",
|
|
3490
3568
|
},
|
|
@@ -3494,6 +3572,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3494
3572
|
summaryLabel: "Claude",
|
|
3495
3573
|
detected: claudeDetected,
|
|
3496
3574
|
recommended: true,
|
|
3575
|
+
installable: true,
|
|
3497
3576
|
icon: "✳",
|
|
3498
3577
|
siteUrl: "https://code.claude.com",
|
|
3499
3578
|
},
|
|
@@ -3503,6 +3582,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3503
3582
|
summaryLabel: "Continue",
|
|
3504
3583
|
detected: continueDetected,
|
|
3505
3584
|
recommended: true,
|
|
3585
|
+
installable: false,
|
|
3506
3586
|
icon: "▶",
|
|
3507
3587
|
siteUrl: "https://continue.dev",
|
|
3508
3588
|
},
|
|
@@ -3512,6 +3592,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3512
3592
|
summaryLabel: "Cline",
|
|
3513
3593
|
detected: clineDetected,
|
|
3514
3594
|
recommended: true,
|
|
3595
|
+
installable: false,
|
|
3515
3596
|
icon: "◈",
|
|
3516
3597
|
siteUrl: "https://cline.bot",
|
|
3517
3598
|
},
|
|
@@ -3521,6 +3602,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3521
3602
|
summaryLabel: "GSD",
|
|
3522
3603
|
detected: gsdDetected,
|
|
3523
3604
|
recommended: true,
|
|
3605
|
+
installable: false,
|
|
3524
3606
|
icon: "▣",
|
|
3525
3607
|
siteUrl: "https://github.com/gsd-build/gsd-2",
|
|
3526
3608
|
},
|
|
@@ -3530,6 +3612,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3530
3612
|
summaryLabel: "OpenClaw",
|
|
3531
3613
|
detected: hasCommand("openclaw"),
|
|
3532
3614
|
recommended: true,
|
|
3615
|
+
installable: false,
|
|
3533
3616
|
icon: "🦞",
|
|
3534
3617
|
siteUrl: "https://openclaw.ai",
|
|
3535
3618
|
},
|
|
@@ -3539,6 +3622,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3539
3622
|
summaryLabel: "OpenCode",
|
|
3540
3623
|
detected: openCodeDetected,
|
|
3541
3624
|
recommended: true,
|
|
3625
|
+
installable: true,
|
|
3542
3626
|
icon: "⌘",
|
|
3543
3627
|
siteUrl: "https://opencode.ai",
|
|
3544
3628
|
},
|
|
@@ -3548,6 +3632,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3548
3632
|
summaryLabel: "Kilo Code",
|
|
3549
3633
|
detected: kiloDetected,
|
|
3550
3634
|
recommended: true,
|
|
3635
|
+
installable: false,
|
|
3551
3636
|
icon: "⚡",
|
|
3552
3637
|
siteUrl: "https://kilo.ai",
|
|
3553
3638
|
},
|
|
@@ -3557,6 +3642,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3557
3642
|
summaryLabel: "Roo Code",
|
|
3558
3643
|
detected: rooDetected,
|
|
3559
3644
|
recommended: true,
|
|
3645
|
+
installable: false,
|
|
3560
3646
|
icon: "🦘",
|
|
3561
3647
|
siteUrl: "https://roocode.com",
|
|
3562
3648
|
},
|
|
@@ -3566,6 +3652,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3566
3652
|
summaryLabel: "Trae",
|
|
3567
3653
|
detected: traeDetected,
|
|
3568
3654
|
recommended: false,
|
|
3655
|
+
installable: false,
|
|
3569
3656
|
icon: "△",
|
|
3570
3657
|
siteUrl: "https://www.trae.ai",
|
|
3571
3658
|
},
|
|
@@ -3575,6 +3662,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3575
3662
|
summaryLabel: "Aider",
|
|
3576
3663
|
detected: aiderDetected,
|
|
3577
3664
|
recommended: true,
|
|
3665
|
+
installable: true,
|
|
3578
3666
|
icon: "✦",
|
|
3579
3667
|
siteUrl: "https://aider.chat",
|
|
3580
3668
|
},
|
|
@@ -3584,6 +3672,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3584
3672
|
summaryLabel: "Zo",
|
|
3585
3673
|
detected: zoDetected,
|
|
3586
3674
|
recommended: false,
|
|
3675
|
+
installable: false,
|
|
3587
3676
|
icon: "◉",
|
|
3588
3677
|
siteUrl: "https://www.zo.computer",
|
|
3589
3678
|
},
|
|
@@ -3593,6 +3682,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3593
3682
|
summaryLabel: "Hermes",
|
|
3594
3683
|
detected: hermesDetected,
|
|
3595
3684
|
recommended: true,
|
|
3685
|
+
installable: false,
|
|
3596
3686
|
icon: "☿",
|
|
3597
3687
|
siteUrl: "https://hermes-agent.nousresearch.com/docs/",
|
|
3598
3688
|
},
|
|
@@ -3602,6 +3692,11 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3602
3692
|
flagSelection: parseSetupClientFlags(flags.clients),
|
|
3603
3693
|
skipPrompt: flags.yes,
|
|
3604
3694
|
});
|
|
3695
|
+
const installedMissingClients = installSelectedMissingClients({
|
|
3696
|
+
setupClients,
|
|
3697
|
+
selectedClientIds: selectedSetupClients,
|
|
3698
|
+
log: (message) => this.log(message),
|
|
3699
|
+
});
|
|
3605
3700
|
const migrateCodexConversations = await resolveCodexConversationMigrationSelection({
|
|
3606
3701
|
codexSelected: selectedSetupClients.has("codex"),
|
|
3607
3702
|
flagValue: flags["migrate-conversations"],
|
|
@@ -3654,6 +3749,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3654
3749
|
let authSeedCleanup = null;
|
|
3655
3750
|
let stateDbMigration = null;
|
|
3656
3751
|
let modelCacheMigration = null;
|
|
3752
|
+
let installedClientsSummary = installedMissingClients;
|
|
3657
3753
|
let continueConfigPath = null;
|
|
3658
3754
|
let clineConfigPaths = [];
|
|
3659
3755
|
let gsdConfigPaths = [];
|
|
@@ -3716,6 +3812,7 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3716
3812
|
this.log(` - ${modelId}${marker}`);
|
|
3717
3813
|
}
|
|
3718
3814
|
}
|
|
3815
|
+
return;
|
|
3719
3816
|
}
|
|
3720
3817
|
const claudeSelected = selectedSetupClients.has("claude");
|
|
3721
3818
|
const claudeEnvEnabled = claudeSelected && claudeAccess.enabled;
|
|
@@ -3923,6 +4020,9 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3923
4020
|
if (backupSummary) {
|
|
3924
4021
|
summaryNotes.add(`Created a local backup snapshot (${backupSummary.id}) before changing client configs.`);
|
|
3925
4022
|
}
|
|
4023
|
+
if (installedClientsSummary.length > 0) {
|
|
4024
|
+
summaryNotes.add(`Installed missing clients: ${installedClientsSummary.join(", ")}.`);
|
|
4025
|
+
}
|
|
3926
4026
|
if (selectedSetupClients.has("claude") && claudeAccess?.enabled) {
|
|
3927
4027
|
summaryNotes.add("Claude Code: exported ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY.");
|
|
3928
4028
|
if (claudeDesktop3pConfigPathManaged) {
|
|
@@ -3977,6 +4077,9 @@ class SetupCommand extends base_command_1.BaseCommand {
|
|
|
3977
4077
|
this.log(`- Managed config: ${paths_1.managedConfigPath}`);
|
|
3978
4078
|
this.log(`- Backend: ${backendUrl}`);
|
|
3979
4079
|
this.log(`- Auth mode: ${authType}`);
|
|
4080
|
+
if (installedClientsSummary.length > 0) {
|
|
4081
|
+
this.log(`- Installed missing clients: ${installedClientsSummary.join(", ")}`);
|
|
4082
|
+
}
|
|
3980
4083
|
if (backupSummary) {
|
|
3981
4084
|
this.log(`- Backup: ${backupSummary.id} (${backupSummary.directory})`);
|
|
3982
4085
|
}
|
package/dist/lib/backups.js
CHANGED
|
@@ -30,6 +30,21 @@ function shellRcTargets() {
|
|
|
30
30
|
kind: "file",
|
|
31
31
|
}));
|
|
32
32
|
}
|
|
33
|
+
function codexTargets() {
|
|
34
|
+
return [
|
|
35
|
+
["codex-config", "Codex config", node_path_1.default.join(paths_1.codexDir, "config.toml"), "file"],
|
|
36
|
+
["codex-auth", "Codex auth state", node_path_1.default.join(paths_1.codexDir, "auth.json"), "file"],
|
|
37
|
+
["codex-credentials", "Codex credentials", node_path_1.default.join(paths_1.codexDir, ".credentials.json"), "file"],
|
|
38
|
+
["codex-accounts", "Codex accounts directory", node_path_1.default.join(paths_1.codexDir, "accounts"), "directory"],
|
|
39
|
+
["codex-managed", "Codex The Claw Bay managed state", node_path_1.default.join(paths_1.codexDir, "theclawbay.managed.json"), "file"],
|
|
40
|
+
["codex-model-cache", "Codex model cache", node_path_1.default.join(paths_1.codexDir, "models_cache.json"), "file"],
|
|
41
|
+
].map(([id, label, targetPath, kind]) => ({
|
|
42
|
+
id,
|
|
43
|
+
label,
|
|
44
|
+
targetPath,
|
|
45
|
+
kind: kind,
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
33
48
|
function editorSettingsTargets() {
|
|
34
49
|
const home = node_os_1.default.homedir();
|
|
35
50
|
const targets = [];
|
|
@@ -59,12 +74,6 @@ function backupTargets() {
|
|
|
59
74
|
targetPath: paths_1.theclawbayConfigDir,
|
|
60
75
|
kind: "directory",
|
|
61
76
|
},
|
|
62
|
-
{
|
|
63
|
-
id: "codex-home",
|
|
64
|
-
label: "Codex home directory",
|
|
65
|
-
targetPath: paths_1.codexDir,
|
|
66
|
-
kind: "directory",
|
|
67
|
-
},
|
|
68
77
|
{
|
|
69
78
|
id: "continue-home",
|
|
70
79
|
label: "Continue config directory",
|
|
@@ -127,7 +136,7 @@ function backupTargets() {
|
|
|
127
136
|
},
|
|
128
137
|
];
|
|
129
138
|
const deduped = new Map();
|
|
130
|
-
for (const target of [...targets, ...shellRcTargets(), ...editorSettingsTargets()]) {
|
|
139
|
+
for (const target of [...targets, ...codexTargets(), ...shellRcTargets(), ...editorSettingsTargets()]) {
|
|
131
140
|
deduped.set(target.targetPath, target);
|
|
132
141
|
}
|
|
133
142
|
return [...deduped.values()];
|
|
@@ -174,7 +183,13 @@ function formatBackupTimestamp(isoString) {
|
|
|
174
183
|
}
|
|
175
184
|
async function createBackup(reason) {
|
|
176
185
|
const now = new Date();
|
|
177
|
-
const
|
|
186
|
+
const baseId = backupIdFromDate(now);
|
|
187
|
+
let id = baseId;
|
|
188
|
+
let suffix = 2;
|
|
189
|
+
while (await pathExists(node_path_1.default.join(paths_1.theclawbayBackupDir, id))) {
|
|
190
|
+
id = `${baseId}-${suffix}`;
|
|
191
|
+
suffix += 1;
|
|
192
|
+
}
|
|
178
193
|
const backupDirectory = node_path_1.default.join(paths_1.theclawbayBackupDir, id);
|
|
179
194
|
const snapshotRoot = node_path_1.default.join(backupDirectory, "files");
|
|
180
195
|
await ensureCleanDirectory(snapshotRoot);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "theclawbay",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.81",
|
|
4
4
|
"description": "CLI for connecting Codex, Hermes Agent, Gemini-compatible apps, 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": {
|