arisa 2.3.13 → 2.3.15

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/daemon/setup.ts +38 -52
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "2.3.13",
3
+ "version": "2.3.15",
4
4
  "description": "Arisa - dynamic agent runtime with daemon/core architecture that evolves through user interaction",
5
5
  "preferGlobal": true,
6
6
  "bin": {
@@ -255,61 +255,52 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
255
255
  console.log(`Starting ${cli} login...`);
256
256
 
257
257
  try {
258
- // For claude: capture stdout to extract OAuth token while still showing output
258
+ // For claude: run setup-token with full stdio, then read token from credentials or prompt
259
259
  if (cli === "claude") {
260
+ // Run with inherited stdio — user interacts directly, no output capture
260
261
  const proc = Bun.spawn(buildBunWrappedAgentCliCommand(cli, args), {
261
262
  stdin: "inherit",
262
- stdout: "pipe",
263
+ stdout: "inherit",
263
264
  stderr: "inherit",
264
265
  });
265
266
 
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;
267
+ const exitCode = await proc.exited;
268
+ if (exitCode !== 0) {
269
+ console.log(` ✗ claude login failed (exit ${exitCode})`);
270
+ return false;
275
271
  }
276
272
 
277
- const exitCode = await proc.exited;
278
- if (exitCode === 0) {
279
- // Step 1: Strip ANSI escape sequences FIRST (their params contain digits/letters)
280
- const clean = output
281
- .replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "") // CSI: ESC [ params final (e.g. ESC[1C)
282
- .replace(/\x1b\][^\x07]*\x07/g, "") // OSC: ESC ] ... BEL
283
- .replace(/\x1b[()#][A-Za-z0-9]/g, "") // 3-byte: ESC ( B, ESC ) 0, ESC # 8
284
- .replace(/\x1b./g, "") // Remaining 2-byte ESC sequences
285
- .replace(/[\x00-\x09\x0b-\x0c\x0e-\x1f]/g, ""); // Control chars (keep \n \r)
286
-
287
- // Step 2: Find boundaries in clean text
288
- const startIdx = clean.indexOf("sk-ant-");
289
- let token = "";
290
-
291
- if (startIdx >= 0) {
292
- let endIdx = clean.indexOf("Store", startIdx);
293
- if (endIdx < 0) endIdx = clean.indexOf("Use this", startIdx);
294
- if (endIdx < 0) endIdx = startIdx + 200;
295
-
296
- const tokenArea = clean.substring(startIdx, endIdx);
297
- // Step 3: Strip whitespace and any remaining non-token chars
298
- token = tokenArea.replace(/[^A-Za-z0-9_-]/g, "");
299
- }
273
+ // Try to read token from Claude's credentials file
274
+ const claudeDir = isRunningAsRoot() ? "/home/arisa/.claude" : join(process.env.HOME || "~", ".claude");
275
+ const credsPath = join(claudeDir, ".credentials.json");
276
+ let token = "";
277
+
278
+ if (existsSync(credsPath)) {
279
+ try {
280
+ const creds = JSON.parse(readFileSync(credsPath, "utf8"));
281
+ token = creds?.claudeAiOauth?.accessToken || "";
282
+ if (token) console.log(` ✓ token read from ${credsPath}`);
283
+ } catch {}
284
+ }
300
285
 
301
- if (token && token.startsWith("sk-ant-") && token.length > 50 && token.length < 150) {
302
- console.log(` [token] ${token.slice(0, 20)}...${token.slice(-6)} (${token.length} chars)`);
303
- vars.CLAUDE_CODE_OAUTH_TOKEN = token;
304
- process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
305
- saveEnv(vars);
306
- console.log(" ✓ claude token saved to .env");
286
+ // If no credentials file, ask user to paste the token
287
+ if (!token) {
288
+ console.log("\n The token was displayed above. Please paste it here:");
289
+ const pasted = await readLine(" CLAUDE_CODE_OAUTH_TOKEN: ");
290
+ token = pasted.replace(/\s+/g, "").trim();
291
+ }
307
292
 
308
- // Also write credentials file for arisa user (belt + suspenders)
309
- const claudeDir = isRunningAsRoot() ? "/home/arisa/.claude" : join(process.env.HOME || "~", ".claude");
293
+ if (token && token.startsWith("sk-ant-")) {
294
+ console.log(` [token] ${token.slice(0, 20)}...${token.slice(-6)} (${token.length} chars)`);
295
+ vars.CLAUDE_CODE_OAUTH_TOKEN = token;
296
+ process.env.CLAUDE_CODE_OAUTH_TOKEN = token;
297
+ saveEnv(vars);
298
+ console.log(" ✓ claude token saved to .env");
299
+
300
+ // Also write credentials file for arisa user if it doesn't exist
301
+ if (!existsSync(credsPath)) {
310
302
  try {
311
303
  if (!existsSync(claudeDir)) mkdirSync(claudeDir, { recursive: true });
312
- const credsPath = join(claudeDir, ".credentials.json");
313
304
  const creds = {
314
305
  claudeAiOauth: {
315
306
  accessToken: token,
@@ -325,18 +316,13 @@ async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, strin
325
316
  } catch (e) {
326
317
  console.log(` ⚠ could not write credentials file: ${e}`);
327
318
  }
328
- } else {
329
- console.log(` ⚠ token extraction failed (indexOf=${startIdx}, len=${token.length})`);
330
- if (startIdx >= 0) {
331
- console.log(` [clean] ${clean.substring(startIdx, startIdx + 150).replace(/\n/g, "\\n")}`);
332
- }
333
319
  }
334
- console.log(` ✓ claude login successful`);
335
- return true;
336
320
  } else {
337
- console.log(` claude login failed (exit ${exitCode})`);
338
- return false;
321
+ console.log(" no valid token provided");
339
322
  }
323
+
324
+ console.log(` ✓ claude login successful`);
325
+ return true;
340
326
  }
341
327
 
342
328
  // For codex and others: inherit all stdio