arisa 2.2.1 → 2.2.4
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 +10 -1
- package/package.json +1 -1
- package/src/core/processor.ts +1 -1
- package/src/daemon/setup.ts +42 -5
- package/src/shared/ai-cli.ts +5 -1
- package/src/shared/config.ts +5 -0
- package/src/shared/ink-shim.js +5 -0
package/bin/arisa.js
CHANGED
|
@@ -497,7 +497,16 @@ function provisionArisaUser() {
|
|
|
497
497
|
}
|
|
498
498
|
step(true, "Arisa installed for arisa");
|
|
499
499
|
|
|
500
|
-
// 4.
|
|
500
|
+
// 4. Install AI CLIs (before daemon starts — avoids OOM in low-memory environments)
|
|
501
|
+
process.stdout.write(" Installing Claude Code CLI...\n");
|
|
502
|
+
const claudeInstall = runAsInherit("~/.bun/bin/bun add -g @anthropic-ai/claude-code");
|
|
503
|
+
step(claudeInstall.status === 0, "Claude Code CLI");
|
|
504
|
+
|
|
505
|
+
process.stdout.write(" Installing Codex CLI...\n");
|
|
506
|
+
const codexInstall = runAsInherit("~/.bun/bin/bun add -g @openai/codex");
|
|
507
|
+
step(codexInstall.status === 0, "Codex CLI");
|
|
508
|
+
|
|
509
|
+
// 5. Migrate data
|
|
501
510
|
const rootArisa = "/root/.arisa";
|
|
502
511
|
if (existsSync(rootArisa)) {
|
|
503
512
|
const destArisa = "/home/arisa/.arisa";
|
package/package.json
CHANGED
package/src/core/processor.ts
CHANGED
package/src/daemon/setup.ts
CHANGED
|
@@ -143,13 +143,13 @@ export async function runSetup(): Promise<boolean> {
|
|
|
143
143
|
// ─── Phase 2: CLI Installation (first run, interactive) ─────────
|
|
144
144
|
|
|
145
145
|
if (isFirstRun && process.stdin.isTTY) {
|
|
146
|
-
await setupClis(inq);
|
|
146
|
+
await setupClis(inq, vars);
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
return true;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
async function setupClis(inq: typeof import("@inquirer/prompts") | null) {
|
|
152
|
+
async function setupClis(inq: typeof import("@inquirer/prompts") | null, vars: Record<string, string>) {
|
|
153
153
|
let claudeInstalled = isAgentCliInstalled("claude");
|
|
154
154
|
let codexInstalled = isAgentCliInstalled("codex");
|
|
155
155
|
|
|
@@ -202,7 +202,7 @@ async function setupClis(inq: typeof import("@inquirer/prompts") | null) {
|
|
|
202
202
|
}
|
|
203
203
|
if (doLogin) {
|
|
204
204
|
console.log();
|
|
205
|
-
await runInteractiveLogin("claude");
|
|
205
|
+
await runInteractiveLogin("claude", vars);
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
|
|
@@ -216,7 +216,7 @@ async function setupClis(inq: typeof import("@inquirer/prompts") | null) {
|
|
|
216
216
|
}
|
|
217
217
|
if (doLogin) {
|
|
218
218
|
console.log();
|
|
219
|
-
await runInteractiveLogin("codex");
|
|
219
|
+
await runInteractiveLogin("codex", vars);
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
|
|
@@ -244,7 +244,7 @@ async function installCli(cli: AgentCliName): Promise<boolean> {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
async function runInteractiveLogin(cli: AgentCliName): Promise<boolean> {
|
|
247
|
+
async function runInteractiveLogin(cli: AgentCliName, vars: Record<string, string>): Promise<boolean> {
|
|
248
248
|
const args = cli === "claude"
|
|
249
249
|
? ["setup-token"]
|
|
250
250
|
: ["login", "--device-auth"];
|
|
@@ -252,6 +252,43 @@ async function runInteractiveLogin(cli: AgentCliName): Promise<boolean> {
|
|
|
252
252
|
console.log(`Starting ${cli} login...`);
|
|
253
253
|
|
|
254
254
|
try {
|
|
255
|
+
// For claude: capture stdout to extract OAuth token while still showing output
|
|
256
|
+
if (cli === "claude") {
|
|
257
|
+
const proc = Bun.spawn(buildBunWrappedAgentCliCommand(cli, args), {
|
|
258
|
+
stdin: "inherit",
|
|
259
|
+
stdout: "pipe",
|
|
260
|
+
stderr: "inherit",
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
let output = "";
|
|
264
|
+
const reader = (proc.stdout as ReadableStream<Uint8Array>).getReader();
|
|
265
|
+
const decoder = new TextDecoder();
|
|
266
|
+
while (true) {
|
|
267
|
+
const { done, value } = await reader.read();
|
|
268
|
+
if (done) break;
|
|
269
|
+
const chunk = decoder.decode(value, { stream: true });
|
|
270
|
+
process.stdout.write(chunk);
|
|
271
|
+
output += chunk;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
const exitCode = await proc.exited;
|
|
275
|
+
if (exitCode === 0) {
|
|
276
|
+
// Extract token (sk-ant-oat01-...) and save to .env
|
|
277
|
+
const tokenMatch = output.match(/(sk-ant-\S+)/);
|
|
278
|
+
if (tokenMatch) {
|
|
279
|
+
vars.CLAUDE_CODE_OAUTH_TOKEN = tokenMatch[1];
|
|
280
|
+
saveEnv(vars);
|
|
281
|
+
console.log(" ✓ claude token saved to .env");
|
|
282
|
+
}
|
|
283
|
+
console.log(` ✓ claude login successful`);
|
|
284
|
+
return true;
|
|
285
|
+
} else {
|
|
286
|
+
console.log(` ✗ claude login failed (exit ${exitCode})`);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// For codex and others: inherit all stdio
|
|
255
292
|
const proc = Bun.spawn(buildBunWrappedAgentCliCommand(cli, args), {
|
|
256
293
|
stdin: "inherit",
|
|
257
294
|
stdout: "inherit",
|
package/src/shared/ai-cli.ts
CHANGED
|
@@ -54,10 +54,14 @@ export function isAgentCliInstalled(cli: AgentCliName): boolean {
|
|
|
54
54
|
return resolveAgentCliPath(cli) !== null;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
const INK_SHIM = join(dirname(new URL(import.meta.url).pathname), "ink-shim.js");
|
|
58
|
+
|
|
57
59
|
export function buildBunWrappedAgentCliCommand(cli: AgentCliName, args: string[]): string[] {
|
|
58
60
|
const cliPath = resolveAgentCliPath(cli);
|
|
59
61
|
if (!cliPath) {
|
|
60
62
|
throw new Error(`${cli} CLI not found`);
|
|
61
63
|
}
|
|
62
|
-
|
|
64
|
+
// Preload shim that patches process.stdin.setRawMode to prevent Ink crash
|
|
65
|
+
// when running without a TTY (systemd, su -c, etc.)
|
|
66
|
+
return ["bun", "--preload", INK_SHIM, cliPath, ...args];
|
|
63
67
|
}
|
package/src/shared/config.ts
CHANGED
|
@@ -39,6 +39,11 @@ function loadEnvFile(): Record<string, string> {
|
|
|
39
39
|
|
|
40
40
|
const envFile = loadEnvFile();
|
|
41
41
|
|
|
42
|
+
// Inject .env vars into process.env so child processes inherit them
|
|
43
|
+
for (const [key, value] of Object.entries(envFile)) {
|
|
44
|
+
if (!process.env[key]) process.env[key] = value;
|
|
45
|
+
}
|
|
46
|
+
|
|
42
47
|
function env(key: string): string | undefined {
|
|
43
48
|
return process.env[key] || envFile[key];
|
|
44
49
|
}
|