arisa 2.0.3 → 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/README.md +9 -5
- package/bin/arisa.js +1 -1
- package/package.json +2 -2
- package/src/core/index.ts +1 -3
- package/src/core/intent.ts +11 -4
- package/src/core/onboarding.ts +3 -2
- package/src/core/processor.ts +4 -6
- package/src/daemon/agent-cli.ts +16 -6
- package/src/daemon/codex-login.ts +5 -4
- package/src/shared/ai-cli.ts +22 -0
package/README.md
CHANGED
|
@@ -10,15 +10,19 @@ Arisa is intentionally dynamic: the project grows as the user builds a relations
|
|
|
10
10
|
|
|
11
11
|
Arisa can execute actions with operational control over the system where it runs. Before deploying it, make sure you understand and accept the associated security risks. It is strongly recommended to run Arisa in an isolated environment (for example, a Docker container or a dedicated VPS) that does not store sensitive information or critical assets.
|
|
12
12
|
|
|
13
|
-
##
|
|
14
|
-
|
|
15
|
-
Requires [Bun](https://bun.sh).
|
|
16
|
-
For Bun global installs, use your user environment.
|
|
13
|
+
## Requirements and Installation
|
|
17
14
|
|
|
18
15
|
```bash
|
|
19
|
-
|
|
16
|
+
curl -fsSL https://bun.sh/install | bash # Install Bun https://bun.sh
|
|
17
|
+
|
|
18
|
+
bun add -g @anthropic-ai/claude-code # Install Claude CLI (both or one is required)
|
|
19
|
+
bun add -g @openai/codex # Install Codex CLI (both or one is required)
|
|
20
|
+
|
|
21
|
+
bun add -g arisa # Install Arisa CLI
|
|
20
22
|
```
|
|
21
23
|
|
|
24
|
+
## Commands
|
|
25
|
+
|
|
22
26
|
```bash
|
|
23
27
|
arisa # Foreground daemon mode (Ctrl+C to stop)
|
|
24
28
|
arisa start # Start as service (enables autostart with systemd --user)
|
package/bin/arisa.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arisa",
|
|
3
|
-
"version": "2.0.
|
|
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": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"bun": ">=1.0.0"
|
|
21
21
|
},
|
|
22
22
|
"scripts": {
|
|
23
|
-
"arisa": "
|
|
23
|
+
"arisa": "bun ./bin/arisa.js",
|
|
24
24
|
"daemon": "bun src/daemon/index.ts",
|
|
25
25
|
"dev": "bun --watch src/core/index.ts",
|
|
26
26
|
"start": "bun src/daemon/index.ts",
|
package/src/core/index.ts
CHANGED
|
@@ -178,9 +178,7 @@ ${messageText}`;
|
|
|
178
178
|
if (msg.command === "/claude") {
|
|
179
179
|
const deps = checkDeps();
|
|
180
180
|
if (!deps.claude) {
|
|
181
|
-
const hint =
|
|
182
|
-
? "<code>brew install claude-code</code> or <code>bun add -g @anthropic-ai/claude-code</code>"
|
|
183
|
-
: "<code>bun add -g @anthropic-ai/claude-code</code>";
|
|
181
|
+
const hint = "<code>bun add -g @anthropic-ai/claude-code</code>";
|
|
184
182
|
return Response.json({ text: `Claude CLI is not installed.\n${hint}` } as CoreResponse);
|
|
185
183
|
}
|
|
186
184
|
backendState.set(msg.chatId, "claude");
|
package/src/core/intent.ts
CHANGED
|
@@ -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
|
|
55
|
+
return buildBunWrappedAgentCliCommand(
|
|
56
|
+
"claude",
|
|
57
|
+
["--dangerously-skip-permissions", "--model", "haiku", "-p", prompt],
|
|
58
|
+
);
|
|
55
59
|
}
|
|
56
|
-
return
|
|
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 (
|
|
79
|
-
if (
|
|
85
|
+
if (resolveAgentCliPath("claude") !== null) order.push("claude");
|
|
86
|
+
if (resolveAgentCliPath("codex") !== null) order.push("codex");
|
|
80
87
|
return order;
|
|
81
88
|
}
|
|
82
89
|
|
package/src/core/onboarding.ts
CHANGED
|
@@ -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:
|
|
50
|
-
codex:
|
|
50
|
+
claude: isAgentCliInstalled("claude"),
|
|
51
|
+
codex: isAgentCliInstalled("codex"),
|
|
51
52
|
openaiKey: !!config.openaiApiKey,
|
|
52
53
|
os,
|
|
53
54
|
};
|
package/src/core/processor.ts
CHANGED
|
@@ -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(
|
|
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(
|
|
219
|
+
const proc = Bun.spawn(buildBunWrappedAgentCliCommand("codex", args), {
|
|
222
220
|
cwd: config.projectDir,
|
|
223
221
|
stdout: "pipe",
|
|
224
222
|
stderr: "pipe",
|
package/src/daemon/agent-cli.ts
CHANGED
|
@@ -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 =
|
|
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 (
|
|
36
|
-
if (
|
|
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
|
|
51
|
+
return buildBunWrappedAgentCliCommand(
|
|
52
|
+
"claude",
|
|
53
|
+
["--dangerously-skip-permissions", "--model", "sonnet", "-p", prompt],
|
|
54
|
+
);
|
|
47
55
|
}
|
|
48
|
-
return
|
|
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
|
|
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(
|
|
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
|
+
}
|