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 +16 -21
- package/package.json +2 -2
- package/src/daemon/auto-install.ts +2 -5
- package/src/daemon/lifecycle.ts +2 -1
- package/src/daemon/setup.ts +2 -3
- package/src/shared/ai-cli.ts +6 -4
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()
|
|
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
|
|
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.
|
|
449
|
-
|
|
450
|
-
|
|
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 =
|
|
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.
|
|
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
|
-
//
|
|
38
|
-
const cmd =
|
|
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",
|
package/src/daemon/lifecycle.ts
CHANGED
|
@@ -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
|
|
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}`);
|
package/src/daemon/setup.ts
CHANGED
|
@@ -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
|
-
|
|
234
|
-
|
|
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",
|
package/src/shared/ai-cli.ts
CHANGED
|
@@ -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
|
-
|
|
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(
|
|
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(
|
|
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}`];
|