theclawbay 0.3.79 → 0.3.80

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.
@@ -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 mark = option.detected
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
- ? option.recommended
1159
- ? paint("recommended", ansi.green)
1160
- : paint("optional", ansi.yellow)
1161
- : paint("not detected", ansi.red);
1162
- const label = option.detected
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
- hint = `${option.label} ${option.checked ? "selected" : "cleared"}.`;
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) => {
@@ -1265,7 +1319,7 @@ function resolveSetupClientSelection(params) {
1265
1319
  for (const client of setupClients) {
1266
1320
  if (!flagSelection.has(client.id))
1267
1321
  continue;
1268
- if (!client.detected) {
1322
+ if (!client.detected && !client.installable) {
1269
1323
  throw new Error(`${client.label} is not detected on this machine, so it cannot be selected yet.`);
1270
1324
  }
1271
1325
  }
@@ -1276,6 +1330,20 @@ function resolveSetupClientSelection(params) {
1276
1330
  return Promise.resolve(defaults);
1277
1331
  return promptForSetupClients(setupClients);
1278
1332
  }
1333
+ function installSelectedMissingClients(params) {
1334
+ const installed = [];
1335
+ for (const client of params.setupClients) {
1336
+ if (!params.selectedClientIds.has(client.id) || client.detected || !client.installable)
1337
+ continue;
1338
+ const plan = installPlanForSetupClient(client.id);
1339
+ if (!plan)
1340
+ continue;
1341
+ params.log(`Installing ${client.summaryLabel}...`);
1342
+ runInstallPlan(plan);
1343
+ installed.push(client.summaryLabel);
1344
+ }
1345
+ return installed;
1346
+ }
1279
1347
  async function promptForCodexConversationMigration() {
1280
1348
  if (!process.stdin.isTTY || !process.stdout.isTTY)
1281
1349
  return false;
@@ -3485,6 +3553,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3485
3553
  summaryLabel: "Codex",
3486
3554
  detected: codexDetected,
3487
3555
  recommended: true,
3556
+ installable: true,
3488
3557
  icon: "◎",
3489
3558
  siteUrl: "https://openai.com/codex",
3490
3559
  },
@@ -3494,6 +3563,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3494
3563
  summaryLabel: "Claude",
3495
3564
  detected: claudeDetected,
3496
3565
  recommended: true,
3566
+ installable: true,
3497
3567
  icon: "✳",
3498
3568
  siteUrl: "https://code.claude.com",
3499
3569
  },
@@ -3503,6 +3573,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3503
3573
  summaryLabel: "Continue",
3504
3574
  detected: continueDetected,
3505
3575
  recommended: true,
3576
+ installable: false,
3506
3577
  icon: "▶",
3507
3578
  siteUrl: "https://continue.dev",
3508
3579
  },
@@ -3512,6 +3583,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3512
3583
  summaryLabel: "Cline",
3513
3584
  detected: clineDetected,
3514
3585
  recommended: true,
3586
+ installable: false,
3515
3587
  icon: "◈",
3516
3588
  siteUrl: "https://cline.bot",
3517
3589
  },
@@ -3521,6 +3593,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3521
3593
  summaryLabel: "GSD",
3522
3594
  detected: gsdDetected,
3523
3595
  recommended: true,
3596
+ installable: false,
3524
3597
  icon: "▣",
3525
3598
  siteUrl: "https://github.com/gsd-build/gsd-2",
3526
3599
  },
@@ -3530,6 +3603,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3530
3603
  summaryLabel: "OpenClaw",
3531
3604
  detected: hasCommand("openclaw"),
3532
3605
  recommended: true,
3606
+ installable: false,
3533
3607
  icon: "🦞",
3534
3608
  siteUrl: "https://openclaw.ai",
3535
3609
  },
@@ -3539,6 +3613,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3539
3613
  summaryLabel: "OpenCode",
3540
3614
  detected: openCodeDetected,
3541
3615
  recommended: true,
3616
+ installable: true,
3542
3617
  icon: "⌘",
3543
3618
  siteUrl: "https://opencode.ai",
3544
3619
  },
@@ -3548,6 +3623,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3548
3623
  summaryLabel: "Kilo Code",
3549
3624
  detected: kiloDetected,
3550
3625
  recommended: true,
3626
+ installable: false,
3551
3627
  icon: "⚡",
3552
3628
  siteUrl: "https://kilo.ai",
3553
3629
  },
@@ -3557,6 +3633,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3557
3633
  summaryLabel: "Roo Code",
3558
3634
  detected: rooDetected,
3559
3635
  recommended: true,
3636
+ installable: false,
3560
3637
  icon: "🦘",
3561
3638
  siteUrl: "https://roocode.com",
3562
3639
  },
@@ -3566,6 +3643,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3566
3643
  summaryLabel: "Trae",
3567
3644
  detected: traeDetected,
3568
3645
  recommended: false,
3646
+ installable: false,
3569
3647
  icon: "△",
3570
3648
  siteUrl: "https://www.trae.ai",
3571
3649
  },
@@ -3575,6 +3653,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3575
3653
  summaryLabel: "Aider",
3576
3654
  detected: aiderDetected,
3577
3655
  recommended: true,
3656
+ installable: true,
3578
3657
  icon: "✦",
3579
3658
  siteUrl: "https://aider.chat",
3580
3659
  },
@@ -3584,6 +3663,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3584
3663
  summaryLabel: "Zo",
3585
3664
  detected: zoDetected,
3586
3665
  recommended: false,
3666
+ installable: false,
3587
3667
  icon: "◉",
3588
3668
  siteUrl: "https://www.zo.computer",
3589
3669
  },
@@ -3593,6 +3673,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3593
3673
  summaryLabel: "Hermes",
3594
3674
  detected: hermesDetected,
3595
3675
  recommended: true,
3676
+ installable: false,
3596
3677
  icon: "☿",
3597
3678
  siteUrl: "https://hermes-agent.nousresearch.com/docs/",
3598
3679
  },
@@ -3602,6 +3683,11 @@ class SetupCommand extends base_command_1.BaseCommand {
3602
3683
  flagSelection: parseSetupClientFlags(flags.clients),
3603
3684
  skipPrompt: flags.yes,
3604
3685
  });
3686
+ const installedMissingClients = installSelectedMissingClients({
3687
+ setupClients,
3688
+ selectedClientIds: selectedSetupClients,
3689
+ log: (message) => this.log(message),
3690
+ });
3605
3691
  const migrateCodexConversations = await resolveCodexConversationMigrationSelection({
3606
3692
  codexSelected: selectedSetupClients.has("codex"),
3607
3693
  flagValue: flags["migrate-conversations"],
@@ -3654,6 +3740,7 @@ class SetupCommand extends base_command_1.BaseCommand {
3654
3740
  let authSeedCleanup = null;
3655
3741
  let stateDbMigration = null;
3656
3742
  let modelCacheMigration = null;
3743
+ let installedClientsSummary = installedMissingClients;
3657
3744
  let continueConfigPath = null;
3658
3745
  let clineConfigPaths = [];
3659
3746
  let gsdConfigPaths = [];
@@ -3923,6 +4010,9 @@ class SetupCommand extends base_command_1.BaseCommand {
3923
4010
  if (backupSummary) {
3924
4011
  summaryNotes.add(`Created a local backup snapshot (${backupSummary.id}) before changing client configs.`);
3925
4012
  }
4013
+ if (installedClientsSummary.length > 0) {
4014
+ summaryNotes.add(`Installed missing clients: ${installedClientsSummary.join(", ")}.`);
4015
+ }
3926
4016
  if (selectedSetupClients.has("claude") && claudeAccess?.enabled) {
3927
4017
  summaryNotes.add("Claude Code: exported ANTHROPIC_BASE_URL and ANTHROPIC_API_KEY.");
3928
4018
  if (claudeDesktop3pConfigPathManaged) {
@@ -3977,6 +4067,9 @@ class SetupCommand extends base_command_1.BaseCommand {
3977
4067
  this.log(`- Managed config: ${paths_1.managedConfigPath}`);
3978
4068
  this.log(`- Backend: ${backendUrl}`);
3979
4069
  this.log(`- Auth mode: ${authType}`);
4070
+ if (installedClientsSummary.length > 0) {
4071
+ this.log(`- Installed missing clients: ${installedClientsSummary.join(", ")}`);
4072
+ }
3980
4073
  if (backupSummary) {
3981
4074
  this.log(`- Backup: ${backupSummary.id} (${backupSummary.directory})`);
3982
4075
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theclawbay",
3
- "version": "0.3.79",
3
+ "version": "0.3.80",
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": {