arisa 2.0.4 → 2.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "2.0.4",
3
+ "version": "2.0.5",
4
4
  "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
5
  "preferGlobal": true,
6
6
  "bin": {
@@ -11,6 +11,7 @@
11
11
 
12
12
  import { config } from "../shared/config";
13
13
  import { createLogger } from "../shared/logger";
14
+ import { buildBunWrappedAgentCliCommand, resolveAgentCliPath } from "../shared/ai-cli";
14
15
 
15
16
  const log = createLogger("core");
16
17
 
@@ -51,9 +52,15 @@ Rules:
51
52
 
52
53
  function buildCmd(cli: "claude" | "codex", prompt: string): string[] {
53
54
  if (cli === "claude") {
54
- return ["claude", "--dangerously-skip-permissions", "--model", "haiku", "-p", prompt];
55
+ return buildBunWrappedAgentCliCommand(
56
+ "claude",
57
+ ["--dangerously-skip-permissions", "--model", "haiku", "-p", prompt],
58
+ );
55
59
  }
56
- return ["codex", "exec", "--dangerously-bypass-approvals-and-sandbox", "-C", config.projectDir, prompt];
60
+ return buildBunWrappedAgentCliCommand(
61
+ "codex",
62
+ ["exec", "--dangerously-bypass-approvals-and-sandbox", "-C", config.projectDir, prompt],
63
+ );
57
64
  }
58
65
 
59
66
  // Track which CLI actually works (not just Bun.which, which can find broken shims)
@@ -75,8 +82,8 @@ async function trySpawn(prompt: string, cli: "claude" | "codex"): Promise<string
75
82
  function getCliOrder(): Array<"claude" | "codex"> {
76
83
  if (verifiedCli) return [verifiedCli];
77
84
  const order: Array<"claude" | "codex"> = [];
78
- if (Bun.which("claude") !== null) order.push("claude");
79
- if (Bun.which("codex") !== null) order.push("codex");
85
+ if (resolveAgentCliPath("claude") !== null) order.push("claude");
86
+ if (resolveAgentCliPath("codex") !== null) order.push("codex");
80
87
  return order;
81
88
  }
82
89
 
@@ -13,6 +13,7 @@
13
13
  import { config } from "../shared/config";
14
14
  import { createLogger } from "../shared/logger";
15
15
  import { getOnboardedUsers, addOnboarded as dbAddOnboarded, isOnboarded as dbIsOnboarded } from "../shared/db";
16
+ import { isAgentCliInstalled } from "../shared/ai-cli";
16
17
 
17
18
  const log = createLogger("core");
18
19
 
@@ -46,8 +47,8 @@ export function checkDeps(): DepsStatus {
46
47
  : "Linux";
47
48
 
48
49
  return {
49
- claude: Bun.which("claude") !== null,
50
- codex: Bun.which("codex") !== null,
50
+ claude: isAgentCliInstalled("claude"),
51
+ codex: isAgentCliInstalled("codex"),
51
52
  openaiKey: !!config.openaiApiKey,
52
53
  os,
53
54
  };
@@ -16,6 +16,7 @@ import { getRecentHistory } from "./history";
16
16
  import { shouldContinue } from "./context";
17
17
  import { config } from "../shared/config";
18
18
  import { createLogger } from "../shared/logger";
19
+ import { buildBunWrappedAgentCliCommand } from "../shared/ai-cli";
19
20
  import { existsSync, mkdirSync, readFileSync, appendFileSync } from "fs";
20
21
  import { join } from "path";
21
22
 
@@ -25,10 +26,7 @@ const PROMPT_PREVIEW_MAX = 220;
25
26
  export const CLAUDE_RATE_LIMIT_MESSAGE = "Claude is out of credits right now. Please try again in a few minutes.";
26
27
  export const CODEX_AUTH_REQUIRED_MESSAGE = [
27
28
  "Codex login is required.",
28
- "Check the Arisa daemon logs now and complete the device-auth steps shown there.",
29
- "If the login flow is not running, execute:",
30
- "<code>codex login --device-auth</code>",
31
- "Then send your message again.",
29
+ "Check the Arisa daemon logs now and complete the device-auth steps shown there."
32
30
  ].join("\n");
33
31
 
34
32
  function logActivity(backend: string, model: string | null, durationMs: number, status: string) {
@@ -147,7 +145,7 @@ async function runClaude(message: string, chatId: string): Promise<string> {
147
145
  log.info(`Claude spawn | cmd: claude --dangerously-skip-permissions --model ${model.model} -p <prompt>`);
148
146
  log.debug(`Claude prompt >>>>\n${prompt}\n<<<<`);
149
147
 
150
- const proc = Bun.spawn(["claude", ...args], {
148
+ const proc = Bun.spawn(buildBunWrappedAgentCliCommand("claude", args), {
151
149
  cwd: config.projectDir,
152
150
  stdout: "pipe",
153
151
  stderr: "pipe",
@@ -218,7 +216,7 @@ export async function processWithCodex(message: string): Promise<string> {
218
216
  );
219
217
  log.debug(`Codex prompt >>>>\n${message}\n<<<<`);
220
218
 
221
- const proc = Bun.spawn(["codex", ...args], {
219
+ const proc = Bun.spawn(buildBunWrappedAgentCliCommand("codex", args), {
222
220
  cwd: config.projectDir,
223
221
  stdout: "pipe",
224
222
  stderr: "pipe",
@@ -11,10 +11,15 @@
11
11
 
12
12
  import { config } from "../shared/config";
13
13
  import { createLogger } from "../shared/logger";
14
+ import {
15
+ buildBunWrappedAgentCliCommand,
16
+ resolveAgentCliPath,
17
+ type AgentCliName,
18
+ } from "../shared/ai-cli";
14
19
 
15
20
  const log = createLogger("daemon");
16
21
 
17
- export type AgentCli = "claude" | "codex";
22
+ export type AgentCli = AgentCliName;
18
23
 
19
24
  export interface CliExecutionResult {
20
25
  cli: AgentCli;
@@ -32,8 +37,8 @@ export interface CliFallbackOutcome {
32
37
 
33
38
  export function getAvailableAgentCli(): AgentCli[] {
34
39
  const order: AgentCli[] = [];
35
- if (Bun.which("claude") !== null) order.push("claude");
36
- if (Bun.which("codex") !== null) order.push("codex");
40
+ if (resolveAgentCliPath("claude") !== null) order.push("claude");
41
+ if (resolveAgentCliPath("codex") !== null) order.push("codex");
37
42
  return order;
38
43
  }
39
44
 
@@ -43,9 +48,15 @@ export function getAgentCliLabel(cli: AgentCli): string {
43
48
 
44
49
  function buildCommand(cli: AgentCli, prompt: string): string[] {
45
50
  if (cli === "claude") {
46
- return ["claude", "--dangerously-skip-permissions", "--model", "sonnet", "-p", prompt];
51
+ return buildBunWrappedAgentCliCommand(
52
+ "claude",
53
+ ["--dangerously-skip-permissions", "--model", "sonnet", "-p", prompt],
54
+ );
47
55
  }
48
- return ["codex", "exec", "--dangerously-bypass-approvals-and-sandbox", "-C", config.projectDir, prompt];
56
+ return buildBunWrappedAgentCliCommand(
57
+ "codex",
58
+ ["exec", "--dangerously-bypass-approvals-and-sandbox", "-C", config.projectDir, prompt],
59
+ );
49
60
  }
50
61
 
51
62
  async function runSingleCli(
@@ -116,4 +127,3 @@ function summarizeError(raw: string): string {
116
127
  if (!clean) return "no details";
117
128
  return clean.length > 200 ? `${clean.slice(0, 200)}...` : clean;
118
129
  }
119
-
@@ -3,18 +3,19 @@
3
3
  * @role Trigger Codex device auth flow from Daemon when auth errors are detected.
4
4
  * @responsibilities
5
5
  * - Detect codex auth-required signals in Core responses
6
- * - Run `codex login --device-auth` in background from daemon process
6
+ * - Run `codex login --device-auth` (wrapped via Bun) in background from daemon process
7
7
  * - Avoid duplicate runs with in-progress lock + cooldown
8
8
  * @effects Spawns codex CLI process, writes to daemon logs/terminal
9
9
  */
10
10
 
11
11
  import { config } from "../shared/config";
12
12
  import { createLogger } from "../shared/logger";
13
+ import { buildBunWrappedAgentCliCommand } from "../shared/ai-cli";
13
14
 
14
15
  const log = createLogger("daemon");
15
16
 
16
17
  const AUTH_HINT_PATTERNS = [
17
- /codex login --device-auth/i,
18
+ /codex.*login --device-auth/i,
18
19
  /codex is not authenticated on this server/i,
19
20
  /missing bearer authentication in header/i,
20
21
  ];
@@ -59,12 +60,12 @@ export function maybeStartCodexDeviceAuth(rawCoreText: string, chatId?: string):
59
60
  }
60
61
 
61
62
  async function runCodexDeviceAuth(): Promise<void> {
62
- log.warn("Codex auth required. Starting `codex login --device-auth` now.");
63
+ log.warn("Codex auth required. Starting `bun --bun <path-to-codex> login --device-auth` now.");
63
64
  log.warn("Complete device auth using the URL/code printed below in this Arisa terminal.");
64
65
 
65
66
  let proc: ReturnType<typeof Bun.spawn>;
66
67
  try {
67
- proc = Bun.spawn(["codex", "login", "--device-auth"], {
68
+ proc = Bun.spawn(buildBunWrappedAgentCliCommand("codex", ["login", "--device-auth"]), {
68
69
  cwd: config.projectDir,
69
70
  stdin: "inherit",
70
71
  stdout: "inherit",
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @module shared/ai-cli
3
+ * @role Resolve agent CLI binaries and execute them via Bun runtime.
4
+ */
5
+
6
+ export type AgentCliName = "claude" | "codex";
7
+
8
+ export function resolveAgentCliPath(cli: AgentCliName): string | null {
9
+ return Bun.which(cli);
10
+ }
11
+
12
+ export function isAgentCliInstalled(cli: AgentCliName): boolean {
13
+ return resolveAgentCliPath(cli) !== null;
14
+ }
15
+
16
+ export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]): string[] {
17
+ const cliPath = resolveAgentCliPath(cli);
18
+ if (!cliPath) {
19
+ throw new Error(`${cli} CLI not found in PATH`);
20
+ }
21
+ return ["bun", "--bun", cliPath, ...args];
22
+ }