arisa 2.3.53 → 2.3.55

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/bin/arisa.js CHANGED
@@ -501,7 +501,8 @@ if (isRoot() && arisaUserExists()) {
501
501
 
502
502
  // Pre-flight: install missing CLIs while still root (before su arisa).
503
503
  // arisa user has read+execute but NOT write access to root's bun dir.
504
- function preflightInstallClis() {
504
+ // Uses @inquirer/prompts checkbox when available (same UI as setup.ts).
505
+ async function preflightInstallClis() {
505
506
  const clis = {
506
507
  claude: "@anthropic-ai/claude-code",
507
508
  codex: "@openai/codex",
@@ -517,16 +518,59 @@ function preflightInstallClis() {
517
518
 
518
519
  if (missing.length === 0) return;
519
520
 
520
- process.stdout.write(`[preflight] Installing missing CLIs as root: ${missing.map((m) => m.name).join(", ")}\n`);
521
- for (const { name, pkg } of missing) {
521
+ // Show status
522
+ process.stdout.write("\nCLI Status:\n");
523
+ for (const name of Object.keys(clis)) {
524
+ const installed = existsSync(join(bunBinDir, name));
525
+ const label = name === "claude" ? "Claude" : "Codex";
526
+ process.stdout.write(` ${installed ? "\u2713" : "\u2717"} ${label}${installed ? "" : " \u2014 not installed"}\n`);
527
+ }
528
+
529
+ let toInstall = missing;
530
+
531
+ if (process.stdin.isTTY) {
532
+ // Try @inquirer/prompts for the same checkbox UI as setup.ts
533
+ let inq = null;
534
+ try { inq = await import("@inquirer/prompts"); } catch {}
535
+
536
+ if (inq) {
537
+ const selected = await inq.checkbox({
538
+ message: "Install missing CLIs? (space to select, enter to confirm)",
539
+ choices: missing.map((cli) => ({
540
+ name: `${cli.name === "claude" ? "Claude" : "Codex"} (${cli.pkg})`,
541
+ value: cli,
542
+ checked: true,
543
+ })),
544
+ });
545
+ toInstall = selected;
546
+ } else {
547
+ // Fallback: simple Y/n
548
+ const rl = require("node:readline");
549
+ const ask = (q) =>
550
+ new Promise((resolve) => {
551
+ const iface = rl.createInterface({ input: process.stdin, output: process.stdout });
552
+ iface.question(q, (a) => { iface.close(); resolve(a.trim()); });
553
+ });
554
+ const answer = await ask("\nInstall missing CLIs? (Y/n): ");
555
+ if (answer.toLowerCase() === "n") toInstall = [];
556
+ }
557
+ }
558
+
559
+ if (toInstall.length === 0) {
560
+ process.stdout.write(" Skipping CLI installation.\n");
561
+ return;
562
+ }
563
+
564
+ for (const { name, pkg } of toInstall) {
565
+ process.stdout.write(`\nInstalling ${name}...\n`);
522
566
  const result = spawnSync("bun", ["add", "-g", pkg], {
523
567
  stdio: "inherit",
524
568
  timeout: 180000,
525
569
  });
526
570
  if (result.status === 0) {
527
- process.stdout.write(`[preflight] ${name} installed\n`);
571
+ process.stdout.write(` \u2713 ${name} installed\n`);
528
572
  } else {
529
- process.stdout.write(`[preflight] ${name} install failed\n`);
573
+ process.stdout.write(` \u2717 ${name} install failed\n`);
530
574
  }
531
575
  }
532
576
 
@@ -535,7 +579,7 @@ function preflightInstallClis() {
535
579
  }
536
580
 
537
581
  if (isRoot() && arisaUserExists()) {
538
- preflightInstallClis();
582
+ await preflightInstallClis();
539
583
  }
540
584
 
541
585
  // Then fall through to normal daemon startup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "2.3.53",
3
+ "version": "2.3.55",
4
4
  "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
5
  "keywords": [
6
6
  "tinyclaw",
@@ -140,20 +140,23 @@ export async function runSetup(): Promise<boolean> {
140
140
  }
141
141
 
142
142
  // ─── Phase 2: CLI Installation ──────────────────────────────────
143
+ // When running as root, bin/arisa.js pre-flight already handled CLI
144
+ // installation with the interactive checkbox before switching to arisa.
145
+ // This phase is only needed for direct (non-root) runs.
143
146
 
144
147
  if (process.stdin.isTTY) {
145
148
  let claudeInstalled = isAgentCliInstalled("claude");
146
149
  let codexInstalled = isAgentCliInstalled("codex");
147
150
 
148
- console.log("\nCLI Status:");
149
- console.log(` ${claudeInstalled ? "✓" : "✗"} Claude${claudeInstalled ? "" : " — not installed"}`);
150
- console.log(` ${codexInstalled ? "✓" : "✗"} Codex${codexInstalled ? "" : " — not installed"}`);
151
-
152
151
  const missing: AgentCliName[] = [];
153
152
  if (!claudeInstalled) missing.push("claude");
154
153
  if (!codexInstalled) missing.push("codex");
155
154
 
156
155
  if (missing.length > 0) {
156
+ console.log("\nCLI Status:");
157
+ console.log(` ${claudeInstalled ? "✓" : "✗"} Claude${claudeInstalled ? "" : " — not installed"}`);
158
+ console.log(` ${codexInstalled ? "✓" : "✗"} Codex${codexInstalled ? "" : " — not installed"}`);
159
+
157
160
  let toInstall: AgentCliName[] = [];
158
161
 
159
162
  if (inq) {