arisa 2.3.15 → 2.3.17
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 +2 -4
- package/package.json +14 -2
- package/src/core/processor.ts +20 -3
- package/src/daemon/setup.ts +71 -37
- package/src/shared/ai-cli.ts +2 -2
package/README.md
CHANGED
|
@@ -14,11 +14,9 @@ Arisa can execute actions with operational control over the system where it runs
|
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
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
17
|
bun add -g arisa # Install Arisa CLI
|
|
18
|
+
|
|
19
|
+
# @anthropic-ai/claude-code and @openai/codex (auto-installed if missing)
|
|
22
20
|
```
|
|
23
21
|
|
|
24
22
|
## Commands
|
package/package.json
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "arisa",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.17",
|
|
4
4
|
"description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"tinyclaw",
|
|
7
|
+
"clawbot",
|
|
8
|
+
"moltbot",
|
|
9
|
+
"openclaw",
|
|
10
|
+
"agent",
|
|
11
|
+
"telegram",
|
|
12
|
+
"jarvis",
|
|
13
|
+
"CLAUDE.md",
|
|
14
|
+
"SOUL.md",
|
|
15
|
+
"clasen"
|
|
16
|
+
],
|
|
5
17
|
"preferGlobal": true,
|
|
6
18
|
"bin": {
|
|
7
19
|
"arisa": "./bin/arisa.js"
|
|
@@ -40,4 +52,4 @@
|
|
|
40
52
|
"@types/bun": "latest",
|
|
41
53
|
"@types/crypto-js": "^4.2.2"
|
|
42
54
|
}
|
|
43
|
-
}
|
|
55
|
+
}
|
package/src/core/processor.ts
CHANGED
|
@@ -273,9 +273,26 @@ export function isCodexAuthRequiredResponse(text: string): boolean {
|
|
|
273
273
|
}
|
|
274
274
|
|
|
275
275
|
function summarizeError(raw: string): string {
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
276
|
+
if (!raw.trim()) return "process ended without details.";
|
|
277
|
+
|
|
278
|
+
const lines = raw.split("\n");
|
|
279
|
+
|
|
280
|
+
// Filter out Bun stack-trace source code lines (e.g. "3 | import{createRequire...")
|
|
281
|
+
// and caret pointer lines (e.g. " ^")
|
|
282
|
+
const meaningful = lines.filter(
|
|
283
|
+
(l) => !/^\s*\d+\s*\|/.test(l) && !/^\s*\^+\s*$/.test(l)
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
// Look for explicit error lines first (e.g. "error: ...", "TypeError: ...")
|
|
287
|
+
const errorLine = meaningful.find((l) =>
|
|
288
|
+
/^\s*(error|Error|TypeError|ReferenceError|SyntaxError|RangeError|ENOENT|EACCES|fatal)[:]/i.test(l.trim())
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
const summary = errorLine?.trim()
|
|
292
|
+
|| meaningful.filter((l) => l.trim()).join(" ").trim()
|
|
293
|
+
|| "process ended without details.";
|
|
294
|
+
|
|
295
|
+
const clean = summary.replace(/\s+/g, " ");
|
|
279
296
|
return clean.length > 200 ? clean.slice(0, 200) + "..." : clean;
|
|
280
297
|
}
|
|
281
298
|
|
package/src/daemon/setup.ts
CHANGED
|
@@ -255,52 +255,81 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
|
|
|
255
255
|
console.log(`Starting ${cli} login...`);
|
|
256
256
|
|
|
257
257
|
try {
|
|
258
|
-
// For claude:
|
|
258
|
+
// For claude: capture stdout to extract OAuth token while still showing output
|
|
259
259
|
if (cli === "claude") {
|
|
260
|
-
// Run with inherited stdio — user interacts directly, no output capture
|
|
261
260
|
const proc = Bun.spawn(buildBunWrappedAgentCliCommand(cli, args), {
|
|
262
261
|
stdin: "inherit",
|
|
263
|
-
stdout: "
|
|
262
|
+
stdout: "pipe",
|
|
264
263
|
stderr: "inherit",
|
|
265
264
|
});
|
|
266
265
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
266
|
+
let output = "";
|
|
267
|
+
const reader = (proc.stdout as ReadableStream<Uint8Array>).getReader();
|
|
268
|
+
const decoder = new TextDecoder();
|
|
269
|
+
while (true) {
|
|
270
|
+
const { done, value } = await reader.read();
|
|
271
|
+
if (done) break;
|
|
272
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
273
|
+
process.stdout.write(chunk);
|
|
274
|
+
output += chunk;
|
|
271
275
|
}
|
|
272
276
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
277
|
+
const exitCode = await proc.exited;
|
|
278
|
+
if (exitCode === 0) {
|
|
279
|
+
// Strip ANSI with a state machine (regex can't handle all Ink sequences)
|
|
280
|
+
function stripAnsi(s: string): string {
|
|
281
|
+
let out = "";
|
|
282
|
+
for (let i = 0; i < s.length; i++) {
|
|
283
|
+
if (s.charCodeAt(i) === 0x1b) {
|
|
284
|
+
i++;
|
|
285
|
+
if (i >= s.length) break;
|
|
286
|
+
if (s[i] === "[") {
|
|
287
|
+
// CSI: ESC [ <params 0x20-0x3F>* <final 0x40-0x7E>
|
|
288
|
+
i++;
|
|
289
|
+
while (i < s.length && s.charCodeAt(i) < 0x40) i++;
|
|
290
|
+
// i now on final byte, loop will i++
|
|
291
|
+
} else if (s[i] === "]") {
|
|
292
|
+
// OSC: ESC ] ... BEL(0x07) or ST(ESC \)
|
|
293
|
+
i++;
|
|
294
|
+
while (i < s.length && s.charCodeAt(i) !== 0x07 && s[i] !== "\x1b") i++;
|
|
295
|
+
} else if (s[i] === "(" || s[i] === ")" || s[i] === "#") {
|
|
296
|
+
i++; // skip designator byte
|
|
297
|
+
}
|
|
298
|
+
// else: 2-byte Fe sequence, already skipped
|
|
299
|
+
} else if (s.charCodeAt(i) < 0x20 && s[i] !== "\n" && s[i] !== "\r") {
|
|
300
|
+
// skip control chars
|
|
301
|
+
} else {
|
|
302
|
+
out += s[i];
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
285
307
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const pasted = await readLine(" CLAUDE_CODE_OAUTH_TOKEN: ");
|
|
290
|
-
token = pasted.replace(/\s+/g, "").trim();
|
|
291
|
-
}
|
|
308
|
+
const clean = stripAnsi(output);
|
|
309
|
+
const startIdx = clean.indexOf("sk-ant-");
|
|
310
|
+
let token = "";
|
|
292
311
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
saveEnv(vars);
|
|
298
|
-
console.log(" ✓ claude token saved to .env");
|
|
312
|
+
if (startIdx >= 0) {
|
|
313
|
+
let endIdx = clean.indexOf("Store", startIdx);
|
|
314
|
+
if (endIdx < 0) endIdx = clean.indexOf("Use this", startIdx);
|
|
315
|
+
if (endIdx < 0) endIdx = startIdx + 200;
|
|
299
316
|
|
|
300
|
-
|
|
301
|
-
|
|
317
|
+
const tokenArea = clean.substring(startIdx, endIdx);
|
|
318
|
+
token = tokenArea.replace(/[^A-Za-z0-9_-]/g, "");
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (token && token.startsWith("sk-ant-") && token.length > 50 && token.length < 150) {
|
|
322
|
+
console.log(` [token] ${token.slice(0, 20)}...${token.slice(-6)} (${token.length} chars)`);
|
|
323
|
+
vars.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
324
|
+
process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
325
|
+
saveEnv(vars);
|
|
326
|
+
console.log(" ✓ claude token saved to .env");
|
|
327
|
+
|
|
328
|
+
// Also write credentials file for arisa user (belt + suspenders)
|
|
329
|
+
const claudeDir = isRunningAsRoot() ? "/home/arisa/.claude" : join(process.env.HOME || "~", ".claude");
|
|
302
330
|
try {
|
|
303
331
|
if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true });
|
|
332
|
+
const credsPath = join(claudeDir, ".credentials.json");
|
|
304
333
|
const creds = {
|
|
305
334
|
claudeAiOauth: {
|
|
306
335
|
accessToken: token,
|
|
@@ -316,13 +345,18 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
|
|
|
316
345
|
} catch (e) {
|
|
317
346
|
console.log(` ⚠ could not write credentials file: ${e}`);
|
|
318
347
|
}
|
|
348
|
+
} else {
|
|
349
|
+
console.log(` ⚠ token extraction failed (indexOf=${startIdx}, len=${token.length})`);
|
|
350
|
+
if (startIdx >= 0) {
|
|
351
|
+
console.log(` [clean] ${clean.substring(startIdx, startIdx + 150).replace(/\n/g, "\\n")}`);
|
|
352
|
+
}
|
|
319
353
|
}
|
|
354
|
+
console.log(` ✓ claude login successful`);
|
|
355
|
+
return true;
|
|
320
356
|
} else {
|
|
321
|
-
console.log(
|
|
357
|
+
console.log(` ✗ claude login failed (exit ${exitCode})`);
|
|
358
|
+
return false;
|
|
322
359
|
}
|
|
323
|
-
|
|
324
|
-
console.log(` ✓ claude login successful`);
|
|
325
|
-
return true;
|
|
326
360
|
}
|
|
327
361
|
|
|
328
362
|
// For codex and others: inherit all stdio
|
package/src/shared/ai-cli.ts
CHANGED
|
@@ -100,7 +100,7 @@ export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]
|
|
|
100
100
|
// Run as arisa user — Claude CLI refuses to run as root
|
|
101
101
|
const cliPath = resolveAgentCliPath(cli) || join(ARISA_USER_BUN, cli);
|
|
102
102
|
const shimPath = existsSync(ARISA_INK_SHIM) ? ARISA_INK_SHIM : INK_SHIM;
|
|
103
|
-
const inner = ["bun", "--preload", shimPath, cliPath, ...args].map(shellEscape).join(" ");
|
|
103
|
+
const inner = ["bun", "--bun", "--preload", shimPath, cliPath, ...args].map(shellEscape).join(" ");
|
|
104
104
|
// su without "-" preserves parent env (tokens, keys); explicit HOME/PATH for arisa
|
|
105
105
|
return ["su", "arisa", "-s", "/bin/bash", "-c", `${ARISA_BUN_ENV} && ${buildEnvExports()}${inner}`];
|
|
106
106
|
}
|
|
@@ -111,5 +111,5 @@ export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]
|
|
|
111
111
|
}
|
|
112
112
|
// Preload shim that patches process.stdin.setRawMode to prevent Ink crash
|
|
113
113
|
// when running without a TTY (systemd, su -c, etc.)
|
|
114
|
-
return ["bun", "--preload", INK_SHIM, cliPath, ...args];
|
|
114
|
+
return ["bun", "--bun", "--preload", INK_SHIM, cliPath, ...args];
|
|
115
115
|
}
|