arisa 2.3.26 → 2.3.28

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
@@ -398,10 +398,6 @@ function restartService() {
398
398
  return restartDetachedFallback();
399
399
  }
400
400
 
401
- function printForegroundNotice() {
402
- process.stdout.write("Starting Arisa in foreground. Press Ctrl+C to stop.\n");
403
- process.stdout.write("Use `arisa start` to run it as a background service.\n");
404
- }
405
401
 
406
402
  // ── Root: create arisa user for Core process execution ──────────────
407
403
  // Daemon runs as root. Core runs as user arisa (Claude CLI refuses root).
@@ -416,14 +412,15 @@ function arisaUserExists() {
416
412
  }
417
413
 
418
414
  function isArisaUserProvisioned() {
419
- return arisaUserExists() && existsSync("/home/arisa/.bun/bin/bun");
415
+ return arisaUserExists();
420
416
  }
421
417
 
422
418
  function step(ok, msg) {
423
419
  process.stdout.write(` ${ok ? "\u2713" : "\u2717"} ${msg}\n`);
424
420
  }
425
421
 
426
- const ARISA_BUN_ENV = 'export BUN_INSTALL=/home/arisa/.bun && export PATH=/home/arisa/.bun/bin:$PATH';
422
+ const ROOT_BUN_INSTALL = process.env.BUN_INSTALL || join(homeDir, ".bun");
423
+ const ARISA_BUN_ENV = `export BUN_INSTALL=${ROOT_BUN_INSTALL} && export PATH=${ROOT_BUN_INSTALL}/bin:$PATH`;
427
424
 
428
425
  function provisionArisaUser() {
429
426
  process.stdout.write("Creating user 'arisa' for Claude/Codex CLI execution...\n");
@@ -445,21 +442,20 @@ function provisionArisaUser() {
445
442
  step(false, `Sudo setup skipped: ${e.message || e}`);
446
443
  }
447
444
 
448
- // 3. Install bun for arisa (curl lightweight, no bun child process)
449
- process.stdout.write(" Installing bun for arisa (this may take a minute)...\n");
450
- const bunInstall = spawnSync("su", ["-", "arisa", "-c", "curl -fsSL https://bun.sh/install | bash"], {
451
- stdio: "inherit",
452
- timeout: 180_000,
453
- });
454
- if (bunInstall.status !== 0) {
455
- step(false, "Failed to install bun");
456
- process.exit(1);
457
- }
458
- step(true, "Bun installed for arisa");
445
+ // 3. Give arisa access to root's bun (no separate install needed)
446
+ grantBunAccess();
447
+ step(true, "Access to root's bun granted");
459
448
 
460
449
  process.stdout.write(" Done. Core will run as arisa; Claude/Codex calls are direct.\n\n");
461
450
  }
462
451
 
452
+ function grantBunAccess() {
453
+ // Allow arisa to traverse into /root (execute only, not read)
454
+ spawnSync("chmod", ["o+x", homeDir], { stdio: "ignore" });
455
+ // Allow arisa to read+execute root's bun and globally installed CLIs
456
+ spawnSync("chmod", ["-R", "o+rX", ROOT_BUN_INSTALL], { stdio: "ignore" });
457
+ }
458
+
463
459
  // Provision arisa user if running as root and not yet done
464
460
  if (isRoot() && !isArisaUserProvisioned()) {
465
461
  provisionArisaUser();
@@ -468,6 +464,8 @@ if (isRoot() && !isArisaUserProvisioned()) {
468
464
  // When root + arisa exists: route all runtime data through arisa's home
469
465
  // so Core (running as arisa) and Daemon (root) share the same data dir.
470
466
  if (isRoot() && arisaUserExists()) {
467
+ // Ensure arisa can access root's bun on every startup
468
+ grantBunAccess();
471
469
  const arisaDataDir = "/home/arisa/.arisa";
472
470
  const rootDataDir = join("/root", ".arisa");
473
471
 
@@ -530,15 +528,12 @@ switch (command) {
530
528
  break;
531
529
  case "daemon":
532
530
  case "run": {
533
- if (isDefaultInvocation) {
534
- printForegroundNotice();
535
- }
536
531
  // Single bun process: daemon + core in-process with --watch.
537
532
  // When root, run as arisa (Claude CLI refuses root). su without "-"
538
533
  // preserves parent env (ARISA_DATA_DIR, tokens, API keys).
539
534
  let child;
540
535
  if (isRoot() && arisaUserExists()) {
541
- const bunEnv = "export HOME=/home/arisa && export BUN_INSTALL=/home/arisa/.bun && export PATH=/home/arisa/.bun/bin:$PATH";
536
+ const bunEnv = `export HOME=/home/arisa && ${ARISA_BUN_ENV}`;
542
537
  const cmd = `${bunEnv} && cd ${pkgRoot} && exec bun --watch ${daemonEntry}`;
543
538
  child = spawnSync("su", ["arisa", "-s", "/bin/bash", "-c", cmd], {
544
539
  stdio: "inherit",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "2.3.26",
3
+ "version": "2.3.28",
4
4
  "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
5
  "keywords": [
6
6
  "tinyclaw",
@@ -52,4 +52,4 @@
52
52
  "@types/bun": "latest",
53
53
  "@types/crypto-js": "^4.2.2"
54
54
  }
55
- }
55
+ }
@@ -19,7 +19,6 @@ const CLI_PACKAGES: Record<AgentCliName, string> = {
19
19
  codex: "@openai/codex",
20
20
  };
21
21
 
22
- const ARISA_BUN_ENV = 'export BUN_INSTALL=/home/arisa/.bun && export PATH=/home/arisa/.bun/bin:$PATH';
23
22
  const INSTALL_TIMEOUT = 120_000; // 2min
24
23
 
25
24
  type NotifyFn = (text: string) => Promise<void>;
@@ -34,10 +33,8 @@ async function installCli(cli: AgentCliName): Promise<boolean> {
34
33
  log.info(`Auto-install: installing ${cli} (${pkg})...`);
35
34
 
36
35
  try {
37
- // When running as root, install into arisa user's bun (consistent with setup.ts)
38
- const cmd = isRunningAsRoot()
39
- ? ["su", "-", "arisa", "-c", `${ARISA_BUN_ENV} && bun add -g ${pkg}`]
40
- : ["bun", "add", "-g", pkg];
36
+ // Install into root's bun (arisa has read+execute access)
37
+ const cmd = ["bun", "add", "-g", pkg];
41
38
 
42
39
  const proc = Bun.spawn(cmd, {
43
40
  stdout: "pipe",
@@ -131,7 +131,8 @@ export function startCore() {
131
131
  // (encryption keys, DB, PID files, etc.) before Core reads them.
132
132
  spawnSync("chown", ["-R", "arisa:arisa", config.arisaDir], { stdio: "ignore" });
133
133
 
134
- const bunEnv = "export HOME=/home/arisa && export BUN_INSTALL=/home/arisa/.bun && export PATH=/home/arisa/.bun/bin:$PATH";
134
+ const bunInstall = process.env.BUN_INSTALL || "/root/.bun";
135
+ const bunEnv = `export HOME=/home/arisa && export BUN_INSTALL=${bunInstall} && export PATH=${bunInstall}/bin:$PATH`;
135
136
  const inner = `${bunEnv} && cd ${config.projectDir} && exec bun --watch ${coreEntry}`;
136
137
  cmd = ["su", "arisa", "-s", "/bin/bash", "-c", inner];
137
138
  log.info(`Starting Core as arisa: bun --watch ${coreEntry}`);
@@ -230,9 +230,8 @@ async function setupClis(inq: typeof import("@inquirer/prompts") | null, vars: R
230
230
 
231
231
  async function installCli(cli: AgentCliName): Promise<boolean> {
232
232
  try {
233
- const cmd = isRunningAsRoot()
234
- ? ["su", "-", "arisa", "-c", `export BUN_INSTALL=/home/arisa/.bun && export PATH=/home/arisa/.bun/bin:$PATH && bun add -g ${CLI_PACKAGES[cli]}`]
235
- : ["bun", "add", "-g", CLI_PACKAGES[cli]];
233
+ // Install into root's bun (arisa has read+execute access)
234
+ const cmd = ["bun", "add", "-g", CLI_PACKAGES[cli]];
236
235
  const proc = Bun.spawn(cmd, {
237
236
  stdout: "inherit",
238
237
  stderr: "inherit",
@@ -10,9 +10,11 @@ import { delimiter, dirname, join } from "path";
10
10
 
11
11
  export type AgentCliName = "claude" | "codex";
12
12
 
13
- const ARISA_USER_BUN = "/home/arisa/.bun/bin";
14
13
  const ARISA_HOME = "/home/arisa";
15
- const ARISA_BUN_ENV = `export HOME=${ARISA_HOME} && export BUN_INSTALL=${ARISA_HOME}/.bun && export PATH=${ARISA_USER_BUN}:$PATH`;
14
+ // Use root's bun arisa user has traverse+read access via chmod o+x /root, o+rX /root/.bun
15
+ const ROOT_BUN_INSTALL = process.env.BUN_INSTALL || "/root/.bun";
16
+ const ROOT_BUN_BIN = `${ROOT_BUN_INSTALL}/bin`;
17
+ const ARISA_BUN_ENV = `export HOME=${ARISA_HOME} && export BUN_INSTALL=${ROOT_BUN_INSTALL} && export PATH=${ROOT_BUN_BIN}:$PATH`;
16
18
 
17
19
  export function isRunningAsRoot(): boolean {
18
20
  return process.getuid?.() === 0;
@@ -43,7 +45,7 @@ function candidatePaths(cli: AgentCliName): string[] {
43
45
  // When root, CLIs are installed under arisa user's bun
44
46
  return unique([
45
47
  cliOverrideEnvVar(cli),
46
- join(ARISA_USER_BUN, cli),
48
+ join(ROOT_BUN_BIN, cli),
47
49
  ]);
48
50
  }
49
51
 
@@ -98,7 +100,7 @@ export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]
98
100
  if (isRunningAsRoot()) {
99
101
  // Run as arisa user — Claude CLI refuses to run as root.
100
102
  // This path is used by Daemon fallback calls; Core runs as arisa directly.
101
- const cliPath = resolveAgentCliPath(cli) || join(ARISA_USER_BUN, cli);
103
+ const cliPath = resolveAgentCliPath(cli) || join(ROOT_BUN_BIN, cli);
102
104
  const inner = ["bun", "--bun", INK_SHIM, cliPath, ...args].map(shellEscape).join(" ");
103
105
  // su without "-" preserves parent env (tokens, keys); explicit HOME/PATH for arisa
104
106
  return ["su", "arisa", "-s", "/bin/bash", "-c", `${ARISA_BUN_ENV} && ${buildEnvExports()}${inner}`];