arisa 2.3.27 → 2.3.29
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 +0 -7
- package/package.json +1 -1
- package/src/daemon/agent-cli.ts +1 -1
- package/src/daemon/setup.ts +53 -22
- package/src/shared/ai-cli.ts +2 -2
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).
|
|
@@ -532,9 +528,6 @@ switch (command) {
|
|
|
532
528
|
break;
|
|
533
529
|
case "daemon":
|
|
534
530
|
case "run": {
|
|
535
|
-
if (isDefaultInvocation) {
|
|
536
|
-
printForegroundNotice();
|
|
537
|
-
}
|
|
538
531
|
// Single bun process: daemon + core in-process with --watch.
|
|
539
532
|
// When root, run as arisa (Claude CLI refuses root). su without "-"
|
|
540
533
|
// preserves parent env (ARISA_DATA_DIR, tokens, API keys).
|
package/package.json
CHANGED
package/src/daemon/agent-cli.ts
CHANGED
|
@@ -110,7 +110,7 @@ export async function runWithCliFallback(prompt: string, timeoutMs: number): Pro
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
const reason = result.exitCode === 0
|
|
113
|
-
?
|
|
113
|
+
? `empty output${result.stderr ? ` (stderr: ${summarizeError(result.stderr)})` : ""}`
|
|
114
114
|
: `exit=${result.exitCode}: ${summarizeError(result.stderr || result.output)}`;
|
|
115
115
|
failures.push(`${getAgentCliLabel(cli)} ${reason}`);
|
|
116
116
|
} catch (error) {
|
package/src/daemon/setup.ts
CHANGED
|
@@ -246,6 +246,32 @@ async function installCli(cli: AgentCliName): Promise<boolean> {
|
|
|
246
246
|
}
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/**
|
|
250
|
+
* Read the OAuth token from Claude CLI's credentials file.
|
|
251
|
+
* Claude CLI stores credentials at ~/.claude/.credentials.json after login.
|
|
252
|
+
*/
|
|
253
|
+
function readClaudeCredentialsToken(): string | null {
|
|
254
|
+
const candidateDirs = [
|
|
255
|
+
isRunningAsRoot() ? "/home/arisa/.claude" : null,
|
|
256
|
+
join(process.env.HOME || "~", ".claude"),
|
|
257
|
+
].filter(Boolean) as string[];
|
|
258
|
+
|
|
259
|
+
for (const dir of candidateDirs) {
|
|
260
|
+
const credsPath = join(dir, ".credentials.json");
|
|
261
|
+
if (!existsSync(credsPath)) continue;
|
|
262
|
+
try {
|
|
263
|
+
const raw = JSON.parse(readFileSync(credsPath, "utf8"));
|
|
264
|
+
const token = raw?.claudeAiOauth?.accessToken;
|
|
265
|
+
if (typeof token === "string" && token.startsWith("sk-ant-") && token.length > 50) {
|
|
266
|
+
return token;
|
|
267
|
+
}
|
|
268
|
+
} catch {
|
|
269
|
+
// Malformed file, skip
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
|
|
249
275
|
async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, string>): Promise<boolean> {
|
|
250
276
|
const args = cli === "claude"
|
|
251
277
|
? ["setup-token"]
|
|
@@ -317,6 +343,14 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
|
|
|
317
343
|
token = tokenArea.replace(/[^A-Za-z0-9_-]/g, "");
|
|
318
344
|
}
|
|
319
345
|
|
|
346
|
+
// Fallback: if stdout scraping missed the token, read from Claude CLI's credentials file
|
|
347
|
+
if (!token || !token.startsWith("sk-ant-") || token.length <= 50 || token.length >= 150) {
|
|
348
|
+
token = readClaudeCredentialsToken() || "";
|
|
349
|
+
if (token) {
|
|
350
|
+
console.log(` ✓ token read from credentials file`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
320
354
|
if (token && token.startsWith("sk-ant-") && token.length > 50 && token.length < 150) {
|
|
321
355
|
console.log(` [token] ${token.slice(0, 20)}...${token.slice(-6)} (${token.length} chars)`);
|
|
322
356
|
vars.CLAUDE_CODE_OAUTH_TOKEN = token;
|
|
@@ -324,31 +358,28 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
|
|
|
324
358
|
saveEnv(vars);
|
|
325
359
|
console.log(" ✓ claude token saved to .env");
|
|
326
360
|
|
|
327
|
-
// Also write credentials file for arisa user
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
Bun.spawnSync(["chown", "-R", "arisa:arisa",
|
|
361
|
+
// Also write credentials file for arisa user when running as root
|
|
362
|
+
if (isRunningAsRoot()) {
|
|
363
|
+
const arisaClaudeDir = "/home/arisa/.claude";
|
|
364
|
+
try {
|
|
365
|
+
if (!existsSync(arisaClaudeDir)) mkdirSync(arisaClaudeDir, { recursive: true });
|
|
366
|
+
const credsPath = join(arisaClaudeDir, ".credentials.json");
|
|
367
|
+
const creds = {
|
|
368
|
+
claudeAiOauth: {
|
|
369
|
+
accessToken: token,
|
|
370
|
+
expiresAt: Date.now() + 365 * 24 * 60 * 60 * 1000,
|
|
371
|
+
scopes: ["user:inference", "user:profile"],
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
writeFileSync(credsPath, JSON.stringify(creds, null, 2) + "\n");
|
|
375
|
+
Bun.spawnSync(["chown", "-R", "arisa:arisa", arisaClaudeDir]);
|
|
376
|
+
console.log(` ✓ credentials written to ${credsPath}`);
|
|
377
|
+
} catch (e) {
|
|
378
|
+
console.log(` ⚠ could not write credentials file: ${e}`);
|
|
342
379
|
}
|
|
343
|
-
console.log(` ✓ credentials written to ${credsPath}`);
|
|
344
|
-
} catch (e) {
|
|
345
|
-
console.log(` ⚠ could not write credentials file: ${e}`);
|
|
346
380
|
}
|
|
347
381
|
} else {
|
|
348
|
-
console.log(` ⚠ token
|
|
349
|
-
if (startIdx >= 0) {
|
|
350
|
-
console.log(` [clean] ${clean.substring(startIdx, startIdx + 150).replace(/\n/g, "\\n")}`);
|
|
351
|
-
}
|
|
382
|
+
console.log(` ⚠ token not captured (Claude CLI stored credentials internally)`);
|
|
352
383
|
}
|
|
353
384
|
console.log(` ✓ claude login successful`);
|
|
354
385
|
return true;
|
package/src/shared/ai-cli.ts
CHANGED
|
@@ -101,7 +101,7 @@ export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]
|
|
|
101
101
|
// Run as arisa user — Claude CLI refuses to run as root.
|
|
102
102
|
// This path is used by Daemon fallback calls; Core runs as arisa directly.
|
|
103
103
|
const cliPath = resolveAgentCliPath(cli) || join(ROOT_BUN_BIN, cli);
|
|
104
|
-
const inner = ["bun", "--bun", INK_SHIM, cliPath, ...args].map(shellEscape).join(" ");
|
|
104
|
+
const inner = ["bun", "--bun", "--preload", INK_SHIM, cliPath, ...args].map(shellEscape).join(" ");
|
|
105
105
|
// su without "-" preserves parent env (tokens, keys); explicit HOME/PATH for arisa
|
|
106
106
|
return ["su", "arisa", "-s", "/bin/bash", "-c", `${ARISA_BUN_ENV} && ${buildEnvExports()}${inner}`];
|
|
107
107
|
}
|
|
@@ -112,5 +112,5 @@ export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]
|
|
|
112
112
|
}
|
|
113
113
|
// Preload shim that patches process.stdin.setRawMode to prevent Ink crash
|
|
114
114
|
// when running without a TTY (systemd, su -c, etc.)
|
|
115
|
-
return ["bun", "--bun", INK_SHIM, cliPath, ...args];
|
|
115
|
+
return ["bun", "--bun", "--preload", INK_SHIM, cliPath, ...args];
|
|
116
116
|
}
|