arisa 2.3.37 → 2.3.39

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.3.37",
3
+ "version": "2.3.39",
4
4
  "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
5
  "keywords": [
6
6
  "tinyclaw",
@@ -268,12 +268,18 @@ async function checkCliAuth(inq: typeof import("@inquirer/prompts") | null, vars
268
268
 
269
269
  /**
270
270
  * Quick probe: is this CLI authenticated?
271
- * Claude: `claude auth status` exits 0 and contains "loggedIn": true
272
- * Codex: `codex auth status` or a quick exec check
271
+ * Claude: check CLAUDE_CODE_OAUTH_TOKEN env/.env, or `claude auth status`
272
+ * Codex: no simple auth check, assume OK if installed
273
273
  */
274
274
  async function isCliAuthenticated(cli: AgentCliName): Promise<boolean> {
275
275
  try {
276
276
  if (cli === "claude") {
277
+ // setup-token auth: token lives in env var (not .credentials.json)
278
+ if (process.env.CLAUDE_CODE_OAUTH_TOKEN?.startsWith("sk-ant-")) {
279
+ console.log(`[setup] claude auth via CLAUDE_CODE_OAUTH_TOKEN env var`);
280
+ return true;
281
+ }
282
+ // Native CLI auth: check `claude auth status`
277
283
  const cmd = buildBunWrappedAgentCliCommand("claude", ["auth", "status"], { skipPreload: true });
278
284
  const proc = Bun.spawn(cmd, { stdout: "pipe", stderr: "pipe" });
279
285
  const stdout = await new Response(proc.stdout).text();
@@ -314,8 +320,56 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
314
320
  console.log(`Starting ${cli} login...`);
315
321
 
316
322
  try {
317
- // Let the CLI handle its own credential storage (credentials.json / keychain).
318
- // Don't intercept stdout or save tokens to .env the CLI manages refresh internally.
323
+ if (cli === "claude") {
324
+ // `claude setup-token` generates a long-lived (1 year) OAuth token for
325
+ // headless/CI environments. It prints the token to stdout but does NOT
326
+ // write .credentials.json. We must capture it and save to .env.
327
+ const proc = Bun.spawn(buildBunWrappedAgentCliCommand(cli, args, { skipPreload: true }), {
328
+ stdin: "inherit",
329
+ stdout: "pipe",
330
+ stderr: "inherit",
331
+ });
332
+
333
+ let output = "";
334
+ const reader = (proc.stdout as ReadableStream<Uint8Array>).getReader();
335
+ const decoder = new TextDecoder();
336
+ while (true) {
337
+ const { done, value } = await reader.read();
338
+ if (done) break;
339
+ const chunk = decoder.decode(value, { stream: true });
340
+ process.stdout.write(chunk);
341
+ output += chunk;
342
+ }
343
+
344
+ const exitCode = await proc.exited;
345
+ if (exitCode !== 0) {
346
+ console.log(` ✗ claude login failed (exit ${exitCode})`);
347
+ return false;
348
+ }
349
+
350
+ // Extract token from output (format: sk-ant-oat01-...)
351
+ // The CLI wraps long tokens across multiple lines — collect until blank line, strip whitespace.
352
+ const tokenStartIdx = output.indexOf("sk-ant-oat01-");
353
+ const tokenArea = tokenStartIdx >= 0
354
+ ? output.substring(tokenStartIdx, output.indexOf("\n\n", tokenStartIdx) >>> 0 || tokenStartIdx + 200)
355
+ : "";
356
+ const tokenMatch = tokenArea ? tokenArea.replace(/\s+/g, "").match(/(sk-ant-oat01-[A-Za-z0-9_-]+)/) : null;
357
+ if (tokenMatch) {
358
+ const token = tokenMatch[1];
359
+ console.log(` [token] ${token.slice(0, 20)}...${token.slice(-6)} (${token.length} chars)`);
360
+ vars.CLAUDE_CODE_OAUTH_TOKEN = token;
361
+ process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
362
+ saveEnv(vars);
363
+ console.log(" ✓ token saved to .env");
364
+ } else {
365
+ console.log(" ⚠ could not extract token from output — set CLAUDE_CODE_OAUTH_TOKEN manually in ~/.arisa/.env");
366
+ }
367
+
368
+ console.log(` ✓ claude login successful`);
369
+ return true;
370
+ }
371
+
372
+ // For codex and others: inherit all stdio
319
373
  const proc = Bun.spawn(buildBunWrappedAgentCliCommand(cli, args, { skipPreload: true }), {
320
374
  stdin: "inherit",
321
375
  stdout: "inherit",
@@ -325,16 +379,6 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
325
379
 
326
380
  if (exitCode === 0) {
327
381
  console.log(` ✓ ${cli} login successful`);
328
-
329
- // Clean up stale CLAUDE_CODE_OAUTH_TOKEN from .env if present —
330
- // it overrides the CLI's own credential store and breaks token refresh.
331
- if (cli === "claude" && vars.CLAUDE_CODE_OAUTH_TOKEN) {
332
- delete vars.CLAUDE_CODE_OAUTH_TOKEN;
333
- delete process.env.CLAUDE_CODE_OAUTH_TOKEN;
334
- saveEnv(vars);
335
- console.log(" ✓ removed stale CLAUDE_CODE_OAUTH_TOKEN from .env (CLI manages auth internally)");
336
- }
337
-
338
382
  return true;
339
383
  } else {
340
384
  console.log(` ✗ ${cli} login failed (exit ${exitCode})`);
@@ -81,10 +81,10 @@ export function isAgentCliInstalled(cli: AgentCliName): boolean {
81
81
  const INK_SHIM = join(dirname(new URL(import.meta.url).pathname), "ink-shim.js");
82
82
 
83
83
  // Env vars that must survive the su - login shell reset.
84
- // Note: CLAUDE_CODE_OAUTH_TOKEN intentionally excluded the CLI manages
85
- // its own credentials via ~/.claude/.credentials.json with token refresh.
86
- // Injecting a stale accessToken via env var breaks refresh.
84
+ // CLAUDE_CODE_OAUTH_TOKEN is a long-lived (1 year) token from `claude setup-token`
85
+ // the headless auth method. It must be passed through to the CLI.
87
86
  const PASSTHROUGH_VARS = [
87
+ "CLAUDE_CODE_OAUTH_TOKEN",
88
88
  "ANTHROPIC_API_KEY",
89
89
  "OPENAI_API_KEY",
90
90
  ];