arisa 2.3.24 → 2.3.26

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
@@ -533,16 +533,29 @@ switch (command) {
533
533
  if (isDefaultInvocation) {
534
534
  printForegroundNotice();
535
535
  }
536
- const child = runWithBun([daemonEntry, ...rest]);
536
+ // Single bun process: daemon + core in-process with --watch.
537
+ // When root, run as arisa (Claude CLI refuses root). su without "-"
538
+ // preserves parent env (ARISA_DATA_DIR, tokens, API keys).
539
+ let child;
540
+ if (isRoot() && arisaUserExists()) {
541
+ const bunEnv = "export HOME=/home/arisa && export BUN_INSTALL=/home/arisa/.bun && export PATH=/home/arisa/.bun/bin:$PATH";
542
+ const cmd = `${bunEnv} && cd ${pkgRoot} && exec bun --watch ${daemonEntry}`;
543
+ child = spawnSync("su", ["arisa", "-s", "/bin/bash", "-c", cmd], {
544
+ stdio: "inherit",
545
+ env: process.env,
546
+ });
547
+ } else {
548
+ child = runWithBun(["--watch", daemonEntry, ...rest]);
549
+ }
537
550
  process.exit(child.status === null ? 1 : child.status);
538
551
  }
539
- case "core":
540
- {
541
- const child = runWithBun([coreEntry, ...rest]);
542
- process.exit(child.status === null ? 1 : child.status);
543
- }
552
+ case "core": {
553
+ await import(coreEntry);
554
+ break;
555
+ }
544
556
  case "dev":
545
557
  {
558
+ // dev needs --watch which is a bun CLI flag, so child process required
546
559
  const child = runWithBun(["--watch", coreEntry, ...rest]);
547
560
  process.exit(child.status === null ? 1 : child.status);
548
561
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "2.3.24",
3
+ "version": "2.3.26",
4
4
  "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
5
  "keywords": [
6
6
  "tinyclaw",
@@ -1,15 +1,15 @@
1
1
  /**
2
2
  * @module daemon/index
3
- * @role Entry point for the Daemon process.
3
+ * @role Single-process entry point: Daemon + Core in one bun runtime.
4
4
  * @responsibilities
5
5
  * - Run interactive setup if config is missing
6
6
  * - Start the Telegram channel adapter
7
- * - Spawn Core process with --watch
8
- * - Run HTTP server on :7778 for Core → Daemon pushes (scheduler)
7
+ * - Load Core in-process (HTTP server, Claude CLI, scheduler)
8
+ * - Run HTTP server for Core → Daemon pushes (scheduler)
9
9
  * - Route incoming messages to Core via bridge
10
10
  * - Route Core responses back to channel
11
- * @dependencies All daemon/* modules, shared/*
12
- * @effects Network (Telegram, HTTP servers), spawns Core process
11
+ * @dependencies All daemon/* modules, core/*, shared/*
12
+ * @effects Network (Telegram, HTTP servers), spawns Claude CLI
13
13
  */
14
14
 
15
15
  // Log version at startup
@@ -32,8 +32,7 @@ const { createLogger } = await import("../shared/logger");
32
32
  const { serveWithRetry, claimProcess, releaseProcess, cleanupSocket } = await import("../shared/ports");
33
33
  const { TelegramChannel } = await import("./channels/telegram");
34
34
  const { sendToCore } = await import("./bridge");
35
- const { startCore, stopCore, setLifecycleNotify, waitForCoreReady } = await import("./lifecycle");
36
- const { setAutoFixNotify } = await import("./autofix");
35
+ // lifecycle/autofix removed Core runs in-process, --watch handles restarts
37
36
  const { maybeStartCodexDeviceAuth, setCodexLoginNotify } = await import("./codex-login");
38
37
  const { maybeStartClaudeSetupToken, maybeFeedClaudeCode, setClaudeLoginNotify, isClaudeLoginPending } = await import("./claude-login");
39
38
  const { autoInstallMissingClis, setAutoInstallNotify, setAuthProbeCallback } = await import("./auto-install");
@@ -95,8 +94,6 @@ const sendToAllChats = async (text: string) => {
95
94
  }
96
95
  };
97
96
 
98
- setLifecycleNotify(sendToAllChats);
99
- setAutoFixNotify(sendToAllChats);
100
97
  setAutoInstallNotify(sendToAllChats);
101
98
  setAuthProbeCallback((cli, errorText) => {
102
99
  if (cli === "claude") {
@@ -256,11 +253,13 @@ const pushServer = await serveWithRetry({
256
253
 
257
254
  log.info(`Daemon push server listening on ${config.daemonSocket}`);
258
255
 
259
- // --- Start Core process ---
260
- startCore();
256
+ // --- Load Core in-process (single bun process, no child spawn) ---
257
+ log.info("Loading Core...");
258
+ await import("../core/index.ts");
259
+ log.info("Core loaded");
261
260
 
262
- // --- Auto-install missing CLIs (after Core is up to avoid OOM on low-RAM VPS) ---
263
- waitForCoreReady(30_000).then(() => void autoInstallMissingClis());
261
+ // --- Auto-install missing CLIs (delayed to avoid peak memory) ---
262
+ setTimeout(() => void autoInstallMissingClis(), 5000);
264
263
 
265
264
  // --- Connect Telegram (with retry for 409 conflict from stale polling sessions) ---
266
265
  (async function connectTelegram(maxRetries = 5) {
@@ -284,8 +283,7 @@ waitForCoreReady(30_000).then(() => void autoInstallMissingClis());
284
283
 
285
284
  // --- Graceful shutdown ---
286
285
  function shutdown() {
287
- log.info("Shutting down Daemon...");
288
- stopCore();
286
+ log.info("Shutting down...");
289
287
  cleanupSocket(config.daemonSocket);
290
288
  cleanupSocket(config.coreSocket);
291
289
  releaseProcess("daemon");