@rubytech/create-realagent 1.0.435 → 1.0.436

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/dist/uninstall.js CHANGED
@@ -4,12 +4,29 @@ import { resolve, join } from "node:path";
4
4
  import { homedir } from "node:os";
5
5
  import { createInterface } from "node:readline";
6
6
  const HOME = homedir();
7
- const INSTALL_DIR = resolve(HOME, "maxy");
8
- const LOG_FILE = join("/tmp", `maxy-uninstall-${new Date().toISOString().replace(/[:.]/g, "-")}.log`);
7
+ const PAYLOAD_DIR = resolve(import.meta.dirname, "../payload");
8
+ // Brand manifest read from payload to derive brand-specific installation paths.
9
+ // No fallback: if brand.json is missing, the package is corrupted.
10
+ const BRAND_PATH = join(PAYLOAD_DIR, "platform", "config", "brand.json");
11
+ if (!existsSync(BRAND_PATH)) {
12
+ console.error("FATAL: brand.json not found in payload. Package may be corrupted.");
13
+ process.exit(1);
14
+ }
15
+ let BRAND;
16
+ try {
17
+ BRAND = JSON.parse(readFileSync(BRAND_PATH, "utf-8"));
18
+ }
19
+ catch (err) {
20
+ console.error(`FATAL: Failed to parse brand.json: ${err.message}`);
21
+ process.exit(1);
22
+ }
23
+ const INSTALL_DIR = resolve(HOME, BRAND.installDir);
24
+ const CONFIG_DIR = resolve(HOME, BRAND.configDir);
25
+ const LOG_FILE = join("/tmp", `${BRAND.productName.toLowerCase().replace(/\s+/g, "-")}-uninstall-${new Date().toISOString().replace(/[:.]/g, "-")}.log`);
9
26
  const TOTAL = "10";
10
27
  // ---------------------------------------------------------------------------
11
28
  // Logging — timestamped to console AND persistent log file in /tmp
12
- // (Log lives in /tmp because the uninstall deletes ~/.maxy/)
29
+ // (Log lives in /tmp because the uninstall deletes the config directory)
13
30
  // ---------------------------------------------------------------------------
14
31
  function logFile(msg) {
15
32
  try {
@@ -67,13 +84,13 @@ export function isMaxyInstalled() {
67
84
  // ---------------------------------------------------------------------------
68
85
  function stopServices() {
69
86
  log("1", "Stopping services...");
70
- // Stop maxy user service
87
+ // Stop platform user service
71
88
  try {
72
- spawnSync("systemctl", ["--user", "stop", "maxy"], { stdio: "pipe", timeout: 15_000 });
73
- console.log(" Stopped maxy.service");
89
+ spawnSync("systemctl", ["--user", "stop", BRAND.serviceName.replace(".service", "")], { stdio: "pipe", timeout: 15_000 });
90
+ console.log(` Stopped ${BRAND.serviceName}`);
74
91
  }
75
92
  catch {
76
- console.log(" maxy.service not running");
93
+ console.log(` ${BRAND.serviceName} not running`);
77
94
  }
78
95
  // Stop Neo4j
79
96
  try {
@@ -210,7 +227,7 @@ export function exportData(exportPath) {
210
227
  console.log(" neo4j-admin not found — skipping database export.");
211
228
  }
212
229
  // Copy account config
213
- const accountsDir = resolve(HOME, ".maxy/accounts");
230
+ const accountsDir = resolve(CONFIG_DIR, "accounts");
214
231
  if (existsSync(accountsDir)) {
215
232
  try {
216
233
  const dest = join(exportPath, "accounts");
@@ -222,11 +239,11 @@ export function exportData(exportPath) {
222
239
  }
223
240
  }
224
241
  else {
225
- console.log(" No account config found at ~/.maxy/accounts/");
242
+ console.log(` No account config found at ${accountsDir}`);
226
243
  }
227
244
  // Copy secrets (password, API key) so a fresh install could reuse them
228
245
  for (const file of [".neo4j-password", ".anthropic-api-key", ".admin-pin"]) {
229
- const src = resolve(HOME, ".maxy", file);
246
+ const src = resolve(CONFIG_DIR, file);
230
247
  if (existsSync(src)) {
231
248
  try {
232
249
  cpSync(src, join(exportPath, file));
@@ -243,8 +260,8 @@ export function exportData(exportPath) {
243
260
  function removeAppDirs() {
244
261
  log("4", "Removing application directories...");
245
262
  const dirs = [
246
- { path: resolve(HOME, "maxy"), label: "~/maxy" },
247
- { path: resolve(HOME, ".maxy"), label: "~/.maxy" },
263
+ { path: INSTALL_DIR, label: `~/${BRAND.installDir}` },
264
+ { path: CONFIG_DIR, label: `~/${BRAND.configDir}` },
248
265
  { path: resolve(HOME, ".cloudflared"), label: "~/.cloudflared" },
249
266
  { path: resolve(HOME, ".claude"), label: "~/.claude" },
250
267
  { path: resolve(HOME, ".ollama"), label: "~/.ollama" },
@@ -336,8 +353,8 @@ function removeSystemConfig() {
336
353
  return;
337
354
  }
338
355
  const files = [
339
- { path: "/etc/avahi/services/maxy.service", label: "Avahi mDNS service" },
340
- { path: "/etc/NetworkManager/conf.d/maxy-no-powersave.conf", label: "WiFi power save config" },
356
+ { path: `/etc/avahi/services/${BRAND.hostname}.service`, label: "Avahi mDNS service" },
357
+ { path: `/etc/NetworkManager/conf.d/${BRAND.hostname}-no-powersave.conf`, label: "WiFi power save config" },
341
358
  { path: "/etc/apt/sources.list.d/neo4j.list", label: "Neo4j apt repository" },
342
359
  { path: "/usr/share/keyrings/neo4j.gpg", label: "Neo4j GPG key" },
343
360
  ];
@@ -364,16 +381,17 @@ function removeSystemConfig() {
364
381
  function removeSystemdService() {
365
382
  log("8", "Removing systemd service...");
366
383
  // Disable the service
384
+ const svcUnit = BRAND.serviceName.replace(".service", "");
367
385
  try {
368
- spawnSync("systemctl", ["--user", "disable", "maxy"], { stdio: "pipe" });
386
+ spawnSync("systemctl", ["--user", "disable", svcUnit], { stdio: "pipe" });
369
387
  }
370
388
  catch { /* already disabled or missing */ }
371
389
  // Remove service file
372
- const serviceFile = resolve(HOME, ".config/systemd/user/maxy.service");
390
+ const serviceFile = resolve(HOME, `.config/systemd/user/${BRAND.serviceName}`);
373
391
  if (existsSync(serviceFile)) {
374
392
  try {
375
393
  rmSync(serviceFile);
376
- console.log(" Removed maxy.service");
394
+ console.log(` Removed ${BRAND.serviceName}`);
377
395
  }
378
396
  catch (err) {
379
397
  console.log(` Failed to remove service file: ${err instanceof Error ? err.message : String(err)}`);
@@ -440,8 +458,8 @@ function restoreHostname() {
440
458
  }
441
459
  try {
442
460
  const hostname = execFileSync("hostname", [], { encoding: "utf-8" }).trim();
443
- if (hostname !== "maxy") {
444
- console.log(` Hostname is '${hostname}' — not 'maxy', nothing to restore.`);
461
+ if (hostname !== BRAND.hostname) {
462
+ console.log(` Hostname is '${hostname}' — not '${BRAND.hostname}', nothing to restore.`);
445
463
  return;
446
464
  }
447
465
  // The installer doesn't save the original hostname, so we use a sensible default
@@ -461,14 +479,14 @@ function showRemovalSummary() {
461
479
  console.log("");
462
480
  console.log("The following will be removed:");
463
481
  console.log("");
464
- console.log(" Services: maxy.service, Neo4j, cloudflared, VNC, Ollama");
465
- console.log(" App dirs: ~/maxy/, ~/.maxy/, ~/.claude/, ~/.cloudflared/, ~/.ollama/");
482
+ console.log(` Services: ${BRAND.serviceName}, Neo4j, cloudflared, VNC, Ollama`);
483
+ console.log(` App dirs: ~/${BRAND.installDir}/, ~/${BRAND.configDir}/, ~/.claude/, ~/.cloudflared/, ~/.ollama/`);
466
484
  console.log(" Database: Neo4j data and transaction logs");
467
485
  console.log(" Packages: neo4j, openjdk-17, tigervnc, websockify, novnc, cloudflared");
468
486
  console.log(" Config: avahi service, WiFi power save, apt repos, GPG keys");
469
- console.log(" Systemd: maxy.service unit file, user lingering");
487
+ console.log(` Systemd: ${BRAND.serviceName} unit file, user lingering`);
470
488
  console.log(" Ollama: binary and models");
471
- console.log(" Hostname: restored from 'maxy' to 'raspberrypi'");
489
+ console.log(` Hostname: restored from '${BRAND.hostname}' to 'raspberrypi'`);
472
490
  console.log(" Cloudflare: tunnel and DNS records deleted from Cloudflare's edge");
473
491
  console.log("");
474
492
  console.log(" Node.js and shared system utilities (curl, git, etc.) are NOT removed.");
@@ -492,13 +510,13 @@ async function confirmUninstall() {
492
510
  export async function runUninstall(options) {
493
511
  const PKG_VERSION = JSON.parse(readFileSync(resolve(import.meta.dirname, "../package.json"), "utf-8")).version;
494
512
  console.log("================================================================");
495
- console.log(` Maxy Uninstall (create-maxy v${PKG_VERSION})`);
513
+ console.log(` ${BRAND.productName} Uninstall (create-maxy v${PKG_VERSION})`);
496
514
  console.log("================================================================");
497
515
  console.log(` Log: ${LOG_FILE}`);
498
516
  console.log("");
499
517
  // Check if Maxy is installed
500
518
  if (!isMaxyInstalled()) {
501
- console.error("Maxy is not installed (~/maxy not found). Nothing to uninstall.");
519
+ console.error(`${BRAND.productName} is not installed (~/${BRAND.installDir} not found). Nothing to uninstall.`);
502
520
  process.exit(1);
503
521
  }
504
522
  // Show what will be removed
@@ -546,7 +564,7 @@ export async function runUninstall(options) {
546
564
  console.log("================================================================");
547
565
  if (failures.length === 0) {
548
566
  console.log("");
549
- console.log(" Maxy has been completely removed.");
567
+ console.log(` ${BRAND.productName} has been completely removed.`);
550
568
  console.log("");
551
569
  console.log(" To reinstall: npx -y @rubytech/create-maxy");
552
570
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rubytech/create-realagent",
3
- "version": "1.0.435",
3
+ "version": "1.0.436",
4
4
  "description": "Install Real Agent — Built for agents. By agents.",
5
5
  "bin": {
6
6
  "create-realagent": "./dist/index.js"
@@ -3128,7 +3128,7 @@ async function GET() {
3128
3128
 
3129
3129
  // app/lib/claude-agent.ts
3130
3130
  import Anthropic from "@anthropic-ai/sdk";
3131
- import { spawn } from "child_process";
3131
+ import { spawn as spawn2 } from "child_process";
3132
3132
  import { resolve as resolve4 } from "path";
3133
3133
  import { readFileSync as readFileSync5, readdirSync, existsSync as existsSync5, mkdirSync as mkdirSync2, createWriteStream, statSync as statSync2, unlinkSync } from "fs";
3134
3134
 
@@ -3267,6 +3267,7 @@ function buildX11Env(chromiumWrapperPath) {
3267
3267
  // app/lib/neo4j-store.ts
3268
3268
  import neo4j from "neo4j-driver";
3269
3269
  import { randomUUID } from "crypto";
3270
+ import { spawn } from "child_process";
3270
3271
  import { readFileSync as readFileSync4 } from "fs";
3271
3272
  import { resolve as resolve3 } from "path";
3272
3273
  var PLATFORM_ROOT2 = process.env.MAXY_PLATFORM_ROOT ?? resolve3(process.cwd(), "..");
@@ -3620,47 +3621,162 @@ async function deleteConversation(conversationId) {
3620
3621
  }
3621
3622
  }
3622
3623
  var GENERIC_MESSAGE = /^(h(i|ello|ey|owdy)|yo|sup|thanks|thank you|ok|okay|yes|no|good\s*(morning|afternoon|evening|night)|greetings|what'?s\s*up)[\s!?.,:;]*$/i;
3623
- function deriveLabel(message) {
3624
+ var SESSION_LABEL_MSG_CAP = 500;
3625
+ var SESSION_LABEL_TIMEOUT_MS = 15e3;
3626
+ var SESSION_LABEL_MODEL = "claude-haiku-4-5-20251001";
3627
+ var SESSION_LABEL_MAX_WORDS = 6;
3628
+ var SESSION_LABEL_MAX_ATTEMPTS = 3;
3629
+ var SESSION_LABEL_MAX_STDERR = 2048;
3630
+ function isMessageUseful(message) {
3624
3631
  const trimmed = message.trim();
3625
- if (trimmed.length < 4) return null;
3626
- if (GENERIC_MESSAGE.test(trimmed)) return null;
3627
- if (trimmed.startsWith("[New session.")) return null;
3628
- const firstSentence = trimmed.split(/[.!?\n]/)[0].trim();
3629
- if (firstSentence.length < 4) return null;
3630
- const words = firstSentence.split(/\s+/).slice(0, 8);
3631
- return words.join(" ");
3632
+ if (trimmed.length < 4) return false;
3633
+ if (trimmed.startsWith('{"')) return false;
3634
+ if (GENERIC_MESSAGE.test(trimmed)) return false;
3635
+ if (trimmed.startsWith("[New session.")) return false;
3636
+ return true;
3637
+ }
3638
+ var labelAccumulator = /* @__PURE__ */ new Map();
3639
+ var _spawnOverride = null;
3640
+ var SESSION_LABEL_SYSTEM = `You are a session labeler. Given the opening messages of a conversation with an AI assistant, produce a concise topic label.
3641
+
3642
+ Rules:
3643
+ - Exactly 3 to 6 words
3644
+ - Summarize the user's intent, do not copy verbatim
3645
+ - Capitalize the first word only (sentence case)
3646
+ - No punctuation, no quotes
3647
+ - If the messages are too vague or meaningless to summarize, respond with exactly: SKIP`;
3648
+ async function generateSessionLabel(messages) {
3649
+ const cappedMessages = messages.map((m) => m.slice(0, SESSION_LABEL_MSG_CAP));
3650
+ const userContent = cappedMessages.map((m, i) => `Message ${i + 1}: ${m}`).join("\n");
3651
+ const prompt = `${SESSION_LABEL_SYSTEM}
3652
+
3653
+ ${userContent}`;
3654
+ const args = [
3655
+ "--print",
3656
+ "--model",
3657
+ SESSION_LABEL_MODEL,
3658
+ "--max-turns",
3659
+ "1",
3660
+ "--permission-mode",
3661
+ "dontAsk",
3662
+ prompt
3663
+ ];
3664
+ return new Promise((resolve16) => {
3665
+ let stdout = "";
3666
+ let stderr = "";
3667
+ const spawnFn = _spawnOverride ?? spawn;
3668
+ const proc = spawnFn("claude", args, {
3669
+ stdio: ["ignore", "pipe", "pipe"]
3670
+ });
3671
+ proc.stdout?.on("data", (chunk) => {
3672
+ stdout += chunk.toString("utf-8");
3673
+ });
3674
+ proc.stderr?.on("data", (chunk) => {
3675
+ if (stderr.length < SESSION_LABEL_MAX_STDERR) {
3676
+ stderr += chunk.toString("utf-8").slice(0, SESSION_LABEL_MAX_STDERR - stderr.length);
3677
+ }
3678
+ });
3679
+ const timer = setTimeout(() => {
3680
+ proc.kill("SIGTERM");
3681
+ console.error("[persist] autoLabel: haiku subprocess timed out");
3682
+ resolve16(null);
3683
+ }, SESSION_LABEL_TIMEOUT_MS);
3684
+ proc.on("error", (err) => {
3685
+ clearTimeout(timer);
3686
+ console.error(`[persist] autoLabel: subprocess error \u2014 ${err.message}`);
3687
+ resolve16(null);
3688
+ });
3689
+ proc.on("close", (code) => {
3690
+ clearTimeout(timer);
3691
+ if (code !== 0) {
3692
+ console.error(`[persist] autoLabel: subprocess exited code=${code}${stderr ? ` stderr=${stderr.trim().slice(0, 200)}` : ""}`);
3693
+ resolve16(null);
3694
+ return;
3695
+ }
3696
+ const text = stdout.trim();
3697
+ if (!text) {
3698
+ console.error("[persist] autoLabel: haiku returned empty response");
3699
+ resolve16(null);
3700
+ return;
3701
+ }
3702
+ if (text === "SKIP") {
3703
+ console.error("[persist] autoLabel: haiku returned SKIP \u2014 messages too vague");
3704
+ resolve16(null);
3705
+ return;
3706
+ }
3707
+ const words = text.split(/\s+/).slice(0, SESSION_LABEL_MAX_WORDS);
3708
+ const label = words.join(" ");
3709
+ console.error(`[persist] autoLabel: haiku response="${label}"`);
3710
+ resolve16(label);
3711
+ });
3712
+ });
3632
3713
  }
3633
3714
  async function autoLabelSession(conversationId, userMessage) {
3634
- const label = deriveLabel(userMessage);
3635
- if (!label) return;
3636
- let embedding = null;
3637
- try {
3638
- embedding = await embed(label);
3639
- } catch (err) {
3640
- console.error(`[persist] Conversation embedding failed, labelling without: ${err instanceof Error ? err.message : String(err)}`);
3715
+ if (!conversationId) return;
3716
+ if (!isMessageUseful(userMessage)) {
3717
+ const reason = userMessage.trim().startsWith('{"') ? "JSON envelope" : userMessage.trim().length < 4 ? "too short" : GENERIC_MESSAGE.test(userMessage.trim()) ? "greeting" : "directive";
3718
+ console.error(`[persist] autoLabel: skipped ${conversationId.slice(0, 8)}\u2026 \u2014 ${reason}`);
3719
+ return;
3641
3720
  }
3642
- const session = getSession();
3721
+ let entry = labelAccumulator.get(conversationId);
3722
+ if (!entry) {
3723
+ entry = { messages: [], pending: false, attempts: 0 };
3724
+ labelAccumulator.set(conversationId, entry);
3725
+ }
3726
+ if (entry.attempts >= SESSION_LABEL_MAX_ATTEMPTS) {
3727
+ console.error(`[persist] autoLabel: evicted ${conversationId.slice(0, 8)}\u2026 after ${SESSION_LABEL_MAX_ATTEMPTS} attempts`);
3728
+ labelAccumulator.delete(conversationId);
3729
+ return;
3730
+ }
3731
+ entry.messages.push(userMessage.trim());
3732
+ if (entry.pending) {
3733
+ console.error(`[persist] autoLabel: accumulated for ${conversationId.slice(0, 8)}\u2026 (pending, ${entry.messages.length} msgs)`);
3734
+ return;
3735
+ }
3736
+ entry.pending = true;
3737
+ entry.attempts++;
3643
3738
  try {
3644
- const result = await session.run(
3645
- `MATCH (c:Conversation {conversationId: $conversationId})
3646
- WHERE c.name IS NULL
3647
- WITH c
3648
- OPTIONAL MATCH (m:Message)-[:PART_OF]->(c)
3649
- WHERE m.role = 'user'
3650
- WITH c, count(m) AS userCount
3651
- WHERE userCount <= 3
3652
- SET c.name = $label, c.updatedAt = datetime()
3653
- ${embedding ? ", c.embedding = $embedding" : ""}
3654
- RETURN c.name AS name`,
3655
- { conversationId, label, ...embedding ? { embedding } : {} }
3656
- );
3657
- if (result.records.length > 0) {
3658
- console.error(`[persist] Auto-labeled session ${conversationId.slice(0, 8)}\u2026: "${label}"${embedding ? " (embedded)" : ""}`);
3739
+ const label = await generateSessionLabel(entry.messages);
3740
+ if (!label) {
3741
+ entry.pending = false;
3742
+ return;
3743
+ }
3744
+ const fullLabel = `${label} \xB7 ${conversationId.slice(0, 8)}`;
3745
+ let embedding = null;
3746
+ try {
3747
+ embedding = await embed(fullLabel);
3748
+ } catch (err) {
3749
+ console.error(`[persist] Conversation embedding failed, labelling without: ${err instanceof Error ? err.message : String(err)}`);
3750
+ }
3751
+ const session = getSession();
3752
+ try {
3753
+ const result = await session.run(
3754
+ `MATCH (c:Conversation {conversationId: $conversationId})
3755
+ WHERE c.name IS NULL
3756
+ WITH c
3757
+ OPTIONAL MATCH (m:Message)-[:PART_OF]->(c)
3758
+ WHERE m.role = 'user'
3759
+ WITH c, count(m) AS userCount
3760
+ WHERE userCount <= 3
3761
+ SET c.name = $label, c.updatedAt = datetime()
3762
+ ${embedding ? ", c.embedding = $embedding" : ""}
3763
+ RETURN c.name AS name`,
3764
+ { conversationId, label: fullLabel, ...embedding ? { embedding } : {} }
3765
+ );
3766
+ if (result.records.length > 0) {
3767
+ console.error(`[persist] Auto-labeled session ${conversationId.slice(0, 8)}\u2026: "${fullLabel}"${embedding ? " (embedded)" : ""}`);
3768
+ labelAccumulator.delete(conversationId);
3769
+ }
3770
+ } catch (err) {
3771
+ console.error(`[persist] autoLabelSession failed: ${err instanceof Error ? err.message : String(err)}`);
3772
+ } finally {
3773
+ await session.close();
3659
3774
  }
3660
3775
  } catch (err) {
3661
- console.error(`[persist] autoLabelSession failed: ${err instanceof Error ? err.message : String(err)}`);
3776
+ console.error(`[persist] autoLabel: unexpected error \u2014 ${err instanceof Error ? err.message : String(err)}`);
3662
3777
  } finally {
3663
- await session.close();
3778
+ const currentEntry = labelAccumulator.get(conversationId);
3779
+ if (currentEntry) currentEntry.pending = false;
3664
3780
  }
3665
3781
  }
3666
3782
  var INITIAL_CONFIDENCE = 0.5;
@@ -4552,7 +4668,7 @@ function fetchMcpToolsList(pluginDir) {
4552
4668
  if (!existsSync5(serverPath)) return Promise.resolve([]);
4553
4669
  const startMs = Date.now();
4554
4670
  return new Promise((resolvePromise) => {
4555
- const proc = spawn(process.execPath, [serverPath], {
4671
+ const proc = spawn2(process.execPath, [serverPath], {
4556
4672
  env: {
4557
4673
  ...process.env,
4558
4674
  PLATFORM_ROOT: PLATFORM_ROOT3,
@@ -5190,7 +5306,7 @@ async function fetchMemoryContext(accountId, query, sessionKey, options) {
5190
5306
  }
5191
5307
  const startMs = Date.now();
5192
5308
  return new Promise((resolve16) => {
5193
- const proc = spawn(process.execPath, [serverPath], {
5309
+ const proc = spawn2(process.execPath, [serverPath], {
5194
5310
  env: {
5195
5311
  ...process.env,
5196
5312
  ACCOUNT_ID: accountId,
@@ -5285,7 +5401,7 @@ async function compactTrimmedMessages(accountId, trimmedMessages) {
5285
5401
  if (!existsSync5(serverPath)) return false;
5286
5402
  const briefing = trimmedMessages.map((m) => `[${m.role.toUpperCase()}] ${m.content}`).join("\n\n");
5287
5403
  return new Promise((resolvePromise) => {
5288
- const proc = spawn(process.execPath, [serverPath], {
5404
+ const proc = spawn2(process.execPath, [serverPath], {
5289
5405
  env: { ...process.env, ACCOUNT_ID: accountId }
5290
5406
  });
5291
5407
  let buffer = "";
@@ -5710,7 +5826,7 @@ async function* runCompactionTurn(accountDir, accountId, systemPrompt, resumeSes
5710
5826
  resumeSessionId,
5711
5827
  COMPACTION_PROMPT
5712
5828
  ];
5713
- const proc = spawn("claude", args, {
5829
+ const proc = spawn2("claude", args, {
5714
5830
  cwd: accountDir,
5715
5831
  stdio: ["ignore", "pipe", "pipe"],
5716
5832
  env: { ...process.env, PLATFORM_ROOT: PLATFORM_ROOT3, ACCOUNT_DIR: accountDir }
@@ -6318,7 +6434,7 @@ async function* invokeAdminAgent(message, systemPrompt, accountDir, accountId, a
6318
6434
  }
6319
6435
  const fullMessage = attachments.length > 0 ? message + buildAttachmentMetaText(attachments) : message;
6320
6436
  args.push(fullMessage);
6321
- const proc = spawn("claude", args, {
6437
+ const proc = spawn2("claude", args, {
6322
6438
  cwd: accountDir,
6323
6439
  stdio: ["ignore", "pipe", "pipe"],
6324
6440
  env: { ...process.env, PLATFORM_ROOT: PLATFORM_ROOT3, ACCOUNT_DIR: accountDir }
@@ -6567,7 +6683,7 @@ async function* invokeManagedAdminAgent(message, systemPrompt, accountDir, accou
6567
6683
  specialistsDir,
6568
6684
  fullMessage
6569
6685
  ];
6570
- const proc = spawn("claude", args, {
6686
+ const proc = spawn2("claude", args, {
6571
6687
  cwd: accountDir,
6572
6688
  stdio: ["ignore", "pipe", "pipe"],
6573
6689
  env: { ...process.env, PLATFORM_ROOT: PLATFORM_ROOT3, ACCOUNT_DIR: accountDir }
@@ -9074,7 +9190,7 @@ async function POST8(req) {
9074
9190
  }
9075
9191
 
9076
9192
  // app/api/onboarding/claude-auth/route.ts
9077
- import { spawn as spawn2, execFileSync as execFileSync2 } from "child_process";
9193
+ import { spawn as spawn3, execFileSync as execFileSync2 } from "child_process";
9078
9194
  import { openSync, closeSync, writeFileSync as writeFileSync6, writeSync } from "fs";
9079
9195
  function checkAuthStatus() {
9080
9196
  try {
@@ -9141,7 +9257,7 @@ async function POST9(req) {
9141
9257
  const chromiumWrapper = writeChromiumWrapper();
9142
9258
  const x11Env = buildX11Env(chromiumWrapper);
9143
9259
  const claudeAuthLogFd = openSync(logPath("claude-auth"), "a");
9144
- const claudeProc = spawn2("claude", ["auth", "login"], {
9260
+ const claudeProc = spawn3("claude", ["auth", "login"], {
9145
9261
  env: x11Env,
9146
9262
  stdio: ["ignore", "pipe", "pipe"]
9147
9263
  });
@@ -9799,7 +9915,7 @@ async function GET7() {
9799
9915
  }
9800
9916
 
9801
9917
  // app/api/admin/version/upgrade/route.ts
9802
- import { spawn as spawn3 } from "child_process";
9918
+ import { spawn as spawn4 } from "child_process";
9803
9919
  import { existsSync as existsSync16, statSync as statSync4, writeFileSync as writeFileSync9, readFileSync as readFileSync16, openSync as openSync2, closeSync as closeSync2 } from "fs";
9804
9920
  import { resolve as resolve14, join as join4 } from "path";
9805
9921
  var PLATFORM_ROOT7 = process.env.MAXY_PLATFORM_ROOT ?? resolve14(process.cwd(), "..");
@@ -9851,7 +9967,7 @@ async function POST14(req) {
9851
9967
  invalidateVersionCache();
9852
9968
  try {
9853
9969
  const logFd = openSync2(LOG_FILE, "w");
9854
- const child = spawn3("npx", ["-y", `${upgradePkg}@latest`], {
9970
+ const child = spawn4("npx", ["-y", `${upgradePkg}@latest`], {
9855
9971
  detached: true,
9856
9972
  stdio: ["ignore", logFd, logFd],
9857
9973
  env: { ...process.env, npm_config_yes: "true" },