happy-imou-cloud 2.1.46 → 2.1.48

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 (25) hide show
  1. package/dist/{BaseReasoningProcessor-Bsnew7fc.cjs → BaseReasoningProcessor-CKtDfihV.cjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-Mrdbmfl3.mjs → BaseReasoningProcessor-CM3JbXUC.mjs} +2 -2
  3. package/dist/{ProviderSelectionHandler-gaUVvyCU.cjs → ProviderSelectionHandler-BHKIBw4t.cjs} +2 -2
  4. package/dist/{ProviderSelectionHandler-BymmO261.mjs → ProviderSelectionHandler-vgZ2egD_.mjs} +2 -2
  5. package/dist/{api-DTSpLLTK.mjs → api-CSjP-Z3Y.mjs} +3 -3
  6. package/dist/{api-Bekjk9d5.cjs → api-eaGKJjMt.cjs} +3 -3
  7. package/dist/{command-umgXYSY2.mjs → command-BzPI4N1n.mjs} +2 -3
  8. package/dist/{command-BwhJX0G5.cjs → command-DDoz1Eky.cjs} +2 -3
  9. package/dist/{index-CUVIZLuf.mjs → index-BzsBo3_Z.mjs} +364 -49
  10. package/dist/{index-DkaYNlRO.cjs → index-C8X1VlHZ.cjs} +338 -42
  11. package/dist/index.cjs +2 -3
  12. package/dist/index.mjs +2 -3
  13. package/dist/lib.cjs +1 -1
  14. package/dist/lib.d.cts +2 -0
  15. package/dist/lib.d.mts +2 -0
  16. package/dist/lib.mjs +1 -1
  17. package/dist/{registerKillSessionHandler-hQE08yMO.mjs → registerKillSessionHandler-BHu-3hZQ.mjs} +2 -2
  18. package/dist/{registerKillSessionHandler-BYWJJDre.cjs → registerKillSessionHandler-CLCYBgZX.cjs} +2 -2
  19. package/dist/{runClaude-jpo2aFey.cjs → runClaude-BkUbXE2F.cjs} +4 -5
  20. package/dist/{runClaude-CFeIMCY2.mjs → runClaude-D3CBLW5o.mjs} +4 -5
  21. package/dist/{runCodex-CrxyWcga.cjs → runCodex-CdgrZK7P.cjs} +29 -9
  22. package/dist/{runCodex-ByjUfTyr.mjs → runCodex-DqzdgDwZ.mjs} +29 -9
  23. package/dist/{runGemini-BhIz1N_b.cjs → runGemini-BE05R24D.cjs} +4 -5
  24. package/dist/{runGemini-CihCRgcR.mjs → runGemini-UZuiKe59.mjs} +4 -5
  25. package/package.json +1 -1
@@ -1,28 +1,27 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
- import { l as logger, q as encodeBase64, c as configuration, t as readCredentials, u as ensureSigningCredentials, r as readSettings, v as updateSettings, w as encodeBase64Url, m as delay, x as buildClientHeaders, y as decodeBase64, z as writeCredentialsLegacy, B as writeCredentialsDataKey, C as readDaemonState, D as HAPPY_CLOUD_DAEMON_PORT, E as clearDaemonState, F as packageJson, i as isAuthenticationRequiredError, G as buildSessionRuntimeIndex, I as acquireDaemonLock, J as writeDaemonState, A as ApiClient, K as releaseDaemonLock, L as validateProfileForAgent, M as getProfileEnvironmentVariables, N as clearCredentials, O as clearMachineId, P as readHappyOrgDispatchTruthSnapshot, Q as processHappyOrgRepoRequests, R as readHappyOrgRepoTaskBoard, S as HappyOrgTurnReportSchema, T as recordHappyOrgTurnReport, U as MessageContentSchema, V as buildSocketAuth, W as encrypt, H as HeadTailPreviewBuffer, X as getLatestDaemonLog } from './api-DTSpLLTK.mjs';
2
+ import { l as logger, q as encodeBase64, c as configuration, t as readCredentials, u as ensureSigningCredentials, r as readSettings, v as updateSettings, w as encodeBase64Url, m as delay, x as buildClientHeaders, y as decodeBase64, z as writeCredentialsLegacy, B as writeCredentialsDataKey, C as readDaemonState, D as HAPPY_CLOUD_DAEMON_PORT, E as clearDaemonState, F as packageJson, i as isAuthenticationRequiredError, G as buildSessionRuntimeIndex, I as acquireDaemonLock, J as writeDaemonState, A as ApiClient, K as releaseDaemonLock, L as validateProfileForAgent, M as getProfileEnvironmentVariables, N as clearCredentials, O as clearMachineId, P as readHappyOrgDispatchTruthSnapshot, Q as processHappyOrgRepoRequests, R as readHappyOrgRepoTaskBoard, S as HappyOrgTurnReportSchema, T as recordHappyOrgTurnReport, U as MessageContentSchema, V as buildSocketAuth, W as encrypt, H as HeadTailPreviewBuffer, X as getLatestDaemonLog } from './api-CSjP-Z3Y.mjs';
3
3
  import { z } from 'zod';
4
4
  import fs, { writeFile as writeFile$1, rename, unlink as unlink$1 } from 'fs/promises';
5
- import os$1, { homedir } from 'os';
6
- import * as tmp from 'tmp';
5
+ import os$1, { homedir as homedir$1 } from 'os';
7
6
  import { randomUUID, randomBytes, createCipheriv } from 'node:crypto';
8
7
  import tweetnacl from 'tweetnacl';
9
8
  import axios from 'axios';
10
9
  import qrcode from 'qrcode-terminal';
11
10
  import { writeFile, unlink, readdir, readFile, mkdir } from 'node:fs/promises';
12
11
  import { createRequire } from 'node:module';
13
- import os, { tmpdir, homedir as homedir$1 } from 'node:os';
14
- import path, { join, resolve as resolve$1, dirname as dirname$1, normalize, isAbsolute, delimiter, relative, basename } from 'node:path';
12
+ import os, { tmpdir, homedir } from 'node:os';
13
+ import path, { join, delimiter, resolve as resolve$1, dirname as dirname$1, normalize, isAbsolute, relative, basename } from 'node:path';
15
14
  import open from 'open';
16
15
  import React, { useState } from 'react';
17
16
  import { useInput, Box, Text, render } from 'ink';
18
17
  import { spawn, execSync, exec } from 'child_process';
19
18
  import { dirname, resolve, join as join$1 } from 'path';
20
19
  import { fileURLToPath } from 'url';
21
- import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync, chmodSync, unlinkSync as unlinkSync$1, mkdirSync } from 'fs';
20
+ import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync as writeFileSync$1, chmodSync as chmodSync$1, unlinkSync as unlinkSync$1, mkdirSync as mkdirSync$1 } from 'fs';
22
21
  import { execFileSync, spawn as spawn$2, execSync as execSync$1 } from 'node:child_process';
23
22
  import psList from 'ps-list';
24
23
  import spawn$1 from 'cross-spawn';
25
- import fs$1, { existsSync, readFileSync, readdirSync, statSync, unlinkSync, rmSync, mkdirSync as mkdirSync$1, mkdtempSync, cpSync, realpathSync } from 'node:fs';
24
+ import fs$1, { existsSync, readFileSync, readdirSync, statSync, mkdtempSync, writeFileSync, chmodSync, unlinkSync, mkdirSync, cpSync, rmSync, realpathSync } from 'node:fs';
26
25
  import fastify from 'fastify';
27
26
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
28
27
  import { randomUUID as randomUUID$1, randomBytes as randomBytes$1, createHash } from 'crypto';
@@ -1567,7 +1566,8 @@ function startDaemonControlServer({
1567
1566
  body: z.object({
1568
1567
  directory: z.string(),
1569
1568
  sessionId: z.string().optional(),
1570
- agent: z.enum(["claude", "codex", "gemini"]).optional()
1569
+ agent: z.enum(["claude", "codex", "gemini"]).optional(),
1570
+ launchMode: z.enum(["background", "terminalWindow", "localTerminal"]).optional()
1571
1571
  }),
1572
1572
  response: {
1573
1573
  200: z.object({
@@ -1588,9 +1588,9 @@ function startDaemonControlServer({
1588
1588
  }
1589
1589
  }
1590
1590
  }, async (request, reply) => {
1591
- const { directory, sessionId, agent } = request.body;
1592
- logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}, agent=${agent || "claude"}`);
1593
- const result = await spawnSession({ directory, sessionId, agent });
1591
+ const { directory, sessionId, agent, launchMode } = request.body;
1592
+ logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}, agent=${agent || "claude"}, launchMode=${launchMode || "background"}`);
1593
+ const result = await spawnSession({ directory, sessionId, agent, launchMode });
1594
1594
  switch (result.type) {
1595
1595
  case "success":
1596
1596
  if (!result.sessionId) {
@@ -2334,20 +2334,33 @@ function resolveDaemonSpawnAgent(agent) {
2334
2334
  throw new Error(`Unsupported agent type: '${agent}'. Please update your CLI to the latest version.`);
2335
2335
  }
2336
2336
  }
2337
- function buildDaemonSpawnArgs(agent, resume) {
2337
+ function buildDaemonSpawnArgs(agent, optionsOrResume) {
2338
+ const options = isLegacyResumeOptions(optionsOrResume) ? { resume: optionsOrResume } : optionsOrResume ?? {};
2339
+ const startingMode = options.startingMode ?? "remote";
2340
+ const startedBy = options.startedBy ?? "daemon";
2338
2341
  const args = [
2339
2342
  resolveDaemonSpawnAgent(agent),
2340
2343
  "--happy-starting-mode",
2341
- "remote",
2344
+ startingMode,
2342
2345
  "--started-by",
2343
- "daemon"
2346
+ startedBy
2344
2347
  ];
2345
- const providerSessionId = typeof resume?.providerSessionId === "string" ? resume.providerSessionId.trim() : "";
2348
+ const providerSessionId = typeof options.resume?.providerSessionId === "string" ? options.resume.providerSessionId.trim() : "";
2346
2349
  if (providerSessionId.length > 0) {
2347
2350
  args.push("--resume", providerSessionId);
2348
2351
  }
2349
2352
  return args;
2350
2353
  }
2354
+ function buildTerminalWindowSpawnArgs(agent, resume) {
2355
+ return buildDaemonSpawnArgs(agent, {
2356
+ resume,
2357
+ startingMode: "local",
2358
+ startedBy: "terminal"
2359
+ });
2360
+ }
2361
+ function isLegacyResumeOptions(value) {
2362
+ return Boolean(value && "providerSessionId" in value);
2363
+ }
2351
2364
 
2352
2365
  const SPAWN_SESSION_ERROR_CODES = {
2353
2366
  INVALID_REQUEST: "INVALID_REQUEST",
@@ -2410,6 +2423,157 @@ function buildDaemonChildEnv(baseEnv, extraEnv) {
2410
2423
  return childEnv;
2411
2424
  }
2412
2425
 
2426
+ function quotePosix(value) {
2427
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
2428
+ }
2429
+ function quoteAppleScriptString(value) {
2430
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
2431
+ }
2432
+ function quoteWindowsCmd(value) {
2433
+ return `"${value.replace(/(["^&|<>()%])/g, "^$1")}"`;
2434
+ }
2435
+ function buildRuntimeInvocation(args, platform, entrypointOverride) {
2436
+ const projectRoot = projectPath();
2437
+ const entrypoint = entrypointOverride || join(projectRoot, "dist", "index.mjs");
2438
+ const runtime = isBun() ? "bun" : "node";
2439
+ const runtimeArgs = ["--no-warnings", "--no-deprecation", entrypoint, ...args];
2440
+ const commandParts = [runtime, ...runtimeArgs];
2441
+ if (platform === "win32") {
2442
+ return commandParts.map(quoteWindowsCmd).join(" ");
2443
+ }
2444
+ return commandParts.map(quotePosix).join(" ");
2445
+ }
2446
+ function buildUserFacingPreview(args) {
2447
+ const agent = args[0];
2448
+ if (agent === "claude" || agent === "codex" || agent === "gemini") {
2449
+ return `hicloud ${agent}`;
2450
+ }
2451
+ return `hicloud ${args.join(" ")}`.trim();
2452
+ }
2453
+ function buildPathWithProjectBin(env, platform) {
2454
+ const binPath = join(projectPath(), "node_modules", ".bin");
2455
+ const pathDelimiter = platform === "win32" ? ";" : delimiter;
2456
+ const currentPath = env?.PATH || env?.Path || process.env.PATH || "";
2457
+ return currentPath ? `${binPath}${pathDelimiter}${currentPath}` : binPath;
2458
+ }
2459
+ function isValidEnvironmentVariableName(name) {
2460
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
2461
+ }
2462
+ function escapeWindowsBatchSetValue(value) {
2463
+ return value.replace(/\r?\n/g, "").replace(/%/g, "%%");
2464
+ }
2465
+ function collectLaunchEnv(env, platform) {
2466
+ const result = {};
2467
+ for (const [key, value] of Object.entries(env || {})) {
2468
+ if (typeof value === "string" && isValidEnvironmentVariableName(key)) {
2469
+ result[key] = value;
2470
+ }
2471
+ }
2472
+ result.PATH = buildPathWithProjectBin(env, platform);
2473
+ return result;
2474
+ }
2475
+ function buildTerminalLaunchScriptContent(options) {
2476
+ const platform = options.platform || process.platform;
2477
+ const launchEnv = collectLaunchEnv(options.env, platform);
2478
+ const preview = buildUserFacingPreview(options.args);
2479
+ const runtimeInvocation = buildRuntimeInvocation(options.args, platform, options.entrypoint);
2480
+ if (platform === "win32") {
2481
+ const envLines2 = Object.entries(launchEnv).map(([key, value]) => `set "${key}=${escapeWindowsBatchSetValue(value)}"`).join("\r\n");
2482
+ return [
2483
+ "@echo off",
2484
+ "setlocal",
2485
+ envLines2,
2486
+ `cd /d ${quoteWindowsCmd(options.cwd)}`,
2487
+ `echo $ ${preview}`,
2488
+ runtimeInvocation,
2489
+ "echo.",
2490
+ "echo Happy session command exited. You can close this window.",
2491
+ 'del "%~f0" >nul 2>nul',
2492
+ "endlocal",
2493
+ ""
2494
+ ].join("\r\n");
2495
+ }
2496
+ const envLines = Object.entries(launchEnv).map(([key, value]) => `export ${key}=${quotePosix(value)}`).join("\n");
2497
+ return [
2498
+ "#!/usr/bin/env bash",
2499
+ "set +e",
2500
+ 'rm -f "$0" >/dev/null 2>&1 || true',
2501
+ envLines,
2502
+ `cd ${quotePosix(options.cwd)} || exit $?`,
2503
+ `echo ${quotePosix(`$ ${preview}`)}`,
2504
+ runtimeInvocation,
2505
+ "status=$?",
2506
+ "echo",
2507
+ 'echo "Happy session command exited with status ${status}. You can close this window."',
2508
+ 'exec "${SHELL:-bash}" -l',
2509
+ ""
2510
+ ].join("\n");
2511
+ }
2512
+ function createTerminalLaunchScript(options) {
2513
+ if (options.scriptPath) {
2514
+ return options.scriptPath;
2515
+ }
2516
+ const platform = options.platform || process.platform;
2517
+ const scriptDirectory = mkdtempSync(join(tmpdir(), "happy-terminal-launch-"));
2518
+ const scriptPath = join(scriptDirectory, platform === "win32" ? "launch.cmd" : "launch.sh");
2519
+ writeFileSync(scriptPath, buildTerminalLaunchScriptContent({ ...options, platform }), { encoding: "utf8", mode: 448 });
2520
+ if (platform !== "win32") {
2521
+ chmodSync(scriptPath, 448);
2522
+ }
2523
+ return scriptPath;
2524
+ }
2525
+ function buildTerminalWindowLaunchCommand(options) {
2526
+ const platform = options.platform || process.platform;
2527
+ const scriptPath = createTerminalLaunchScript({ ...options, platform });
2528
+ const preview = buildUserFacingPreview(options.args);
2529
+ if (platform === "win32") {
2530
+ return {
2531
+ command: "cmd.exe",
2532
+ args: ["/d", "/s", "/c", `start "" cmd.exe /d /s /k ${quoteWindowsCmd(scriptPath)}`],
2533
+ options: {
2534
+ cwd: options.cwd,
2535
+ detached: true,
2536
+ stdio: "ignore",
2537
+ env: options.env,
2538
+ windowsHide: false
2539
+ },
2540
+ preview,
2541
+ scriptPath
2542
+ };
2543
+ }
2544
+ if (platform === "darwin") {
2545
+ const appleScript = `tell application "Terminal" to do script ${quoteAppleScriptString(`bash ${quotePosix(scriptPath)}`)}`;
2546
+ return {
2547
+ command: "osascript",
2548
+ args: ["-e", appleScript],
2549
+ options: {
2550
+ cwd: options.cwd,
2551
+ detached: true,
2552
+ stdio: "ignore",
2553
+ env: options.env
2554
+ },
2555
+ preview,
2556
+ scriptPath
2557
+ };
2558
+ }
2559
+ return {
2560
+ command: "x-terminal-emulator",
2561
+ args: ["-e", "bash", scriptPath],
2562
+ options: {
2563
+ cwd: options.cwd,
2564
+ detached: true,
2565
+ stdio: "ignore",
2566
+ env: options.env
2567
+ },
2568
+ preview,
2569
+ scriptPath
2570
+ };
2571
+ }
2572
+ function spawnHappyCLIInTerminalWindow(options) {
2573
+ const launchCommand = buildTerminalWindowLaunchCommand(options);
2574
+ return spawn$2(launchCommand.command, launchCommand.args, launchCommand.options);
2575
+ }
2576
+
2413
2577
  const DIFFERENT_DAEMON_RUNNING_MESSAGE = "A different daemon was started without killing us. We should kill ourselves.";
2414
2578
  function pruneStaleTrackedSessions({
2415
2579
  trackedSessionPids,
@@ -3409,6 +3573,50 @@ function resolveTrackedHappySessionId(opts) {
3409
3573
  return opts.precreatedSessionId ?? opts.requestedSessionId;
3410
3574
  }
3411
3575
 
3576
+ const CODEX_HOME_CONFIG_FILES = [
3577
+ "config.toml",
3578
+ "cap_sid",
3579
+ "version.json",
3580
+ "MEMORY.md"
3581
+ ];
3582
+ const CODEX_HOME_CONFIG_DIRS = [
3583
+ "rules",
3584
+ "skills"
3585
+ ];
3586
+ function copyCodexHomeEntry$1(sourcePath, destPath) {
3587
+ if (!existsSync(sourcePath)) {
3588
+ return;
3589
+ }
3590
+ mkdirSync(dirname$1(destPath), { recursive: true });
3591
+ cpSync(sourcePath, destPath, {
3592
+ recursive: true,
3593
+ force: true,
3594
+ dereference: false,
3595
+ verbatimSymlinks: true
3596
+ });
3597
+ }
3598
+ function createDaemonCodexAuthHome(options) {
3599
+ const sourceHomeDir = options.sourceHomeDir ?? join(homedir(), ".codex");
3600
+ const targetHomeDir = options.tempDir;
3601
+ mkdirSync(targetHomeDir, { recursive: true });
3602
+ for (const fileName of CODEX_HOME_CONFIG_FILES) {
3603
+ try {
3604
+ copyCodexHomeEntry$1(join(sourceHomeDir, fileName), join(targetHomeDir, fileName));
3605
+ } catch (error) {
3606
+ logger.debug(`[codex] Failed to copy source CODEX_HOME file ${fileName} into daemon auth home`, error);
3607
+ }
3608
+ }
3609
+ for (const dirName of CODEX_HOME_CONFIG_DIRS) {
3610
+ try {
3611
+ copyCodexHomeEntry$1(join(sourceHomeDir, dirName), join(targetHomeDir, dirName));
3612
+ } catch (error) {
3613
+ logger.debug(`[codex] Failed to copy source CODEX_HOME directory ${dirName} into daemon auth home`, error);
3614
+ }
3615
+ }
3616
+ writeFileSync(join(targetHomeDir, "auth.json"), options.authJson, "utf8");
3617
+ return targetHomeDir;
3618
+ }
3619
+
3412
3620
  const DEFAULT_SESSION_WEBHOOK_TIMEOUT_MS = 45e3;
3413
3621
  const DEFAULT_TRACKED_SESSION_SWEEP_INTERVAL_MS = 5e3;
3414
3622
  function resolveSessionWebhookTimeoutMs() {
@@ -3523,6 +3731,28 @@ async function startDaemon() {
3523
3731
  let api = null;
3524
3732
  const pidToTrackedSession = /* @__PURE__ */ new Map();
3525
3733
  const pidToAwaiter = /* @__PURE__ */ new Map();
3734
+ const terminalLaunchAwaiters = /* @__PURE__ */ new Map();
3735
+ const normalizePathForSessionMatch = (value) => (value || "").trim().replace(/[\\/]+$/, "");
3736
+ const resolveTerminalLaunchAwaiter = (sessionId, sessionMetadata) => {
3737
+ const reportedDirectory = normalizePathForSessionMatch(sessionMetadata.path);
3738
+ const reportedFlavor = resolveRecoverySpawnAgent(sessionMetadata.flavor);
3739
+ const now = Date.now();
3740
+ for (const [awaiterId, awaiter] of terminalLaunchAwaiters.entries()) {
3741
+ if (awaiter.startedAt - 5e3 > now) {
3742
+ continue;
3743
+ }
3744
+ const directoryMatches = normalizePathForSessionMatch(awaiter.directory) === reportedDirectory;
3745
+ const agentMatches = !awaiter.agent || !reportedFlavor || awaiter.agent === reportedFlavor;
3746
+ if (!directoryMatches || !agentMatches) {
3747
+ continue;
3748
+ }
3749
+ terminalLaunchAwaiters.delete(awaiterId);
3750
+ awaiter.resolve({ type: "success", sessionId });
3751
+ logger.debug(`[DAEMON RUN] Resolved terminal window session awaiter ${awaiterId} for session ${sessionId}`);
3752
+ return true;
3753
+ }
3754
+ return false;
3755
+ };
3526
3756
  const getCurrentChildren = () => Array.from(pidToTrackedSession.values());
3527
3757
  let userScopedObserver = null;
3528
3758
  const removeTrackedSession = (pid, archiveReason) => {
@@ -3571,6 +3801,7 @@ async function startDaemon() {
3571
3801
  };
3572
3802
  pidToTrackedSession.set(pid, trackedSession);
3573
3803
  logger.debug(`[DAEMON RUN] Registered externally-started session ${sessionId}`);
3804
+ resolveTerminalLaunchAwaiter(sessionId, sessionMetadata);
3574
3805
  }
3575
3806
  };
3576
3807
  const spawnSession = async (options) => {
@@ -3619,9 +3850,11 @@ async function startDaemon() {
3619
3850
  const authEnv = {};
3620
3851
  if (options.token) {
3621
3852
  if (options.agent === "codex") {
3622
- const codexHomeDir = tmp.dirSync();
3623
- fs.writeFile(join$1(codexHomeDir.name, "auth.json"), options.token);
3624
- authEnv.CODEX_HOME = codexHomeDir.name;
3853
+ const codexHomeDir = await fs.mkdtemp(join$1(os$1.tmpdir(), "happy-codex-daemon-home-"));
3854
+ authEnv.CODEX_HOME = createDaemonCodexAuthHome({
3855
+ authJson: options.token,
3856
+ tempDir: codexHomeDir
3857
+ });
3625
3858
  } else {
3626
3859
  authEnv.CLAUDE_CODE_OAUTH_TOKEN = options.token;
3627
3860
  }
@@ -3678,6 +3911,84 @@ async function startDaemon() {
3678
3911
  errorMessage: spawnError.errorMessage
3679
3912
  };
3680
3913
  }
3914
+ if (options.launchMode === "terminalWindow" || options.launchMode === "localTerminal") {
3915
+ logger.debug(`[DAEMON RUN] Using visible terminal window spawning`);
3916
+ let args;
3917
+ try {
3918
+ args = buildTerminalWindowSpawnArgs(options.agent, options.resume);
3919
+ } catch (error) {
3920
+ const spawnError = createSpawnSessionError(
3921
+ SPAWN_SESSION_ERROR_CODES.INVALID_REQUEST,
3922
+ error instanceof Error ? error.message : String(error)
3923
+ );
3924
+ return {
3925
+ type: spawnError.type,
3926
+ errorMessage: spawnError.errorMessage
3927
+ };
3928
+ }
3929
+ const terminalEnv = buildDaemonChildEnv(process.env, extraEnv);
3930
+ const terminalProcess = spawnHappyCLIInTerminalWindow({
3931
+ cwd: directory,
3932
+ args,
3933
+ env: terminalEnv
3934
+ });
3935
+ if (!terminalProcess.pid) {
3936
+ logger.debug("[DAEMON RUN] Failed to spawn terminal window - no PID returned");
3937
+ const spawnError = createSpawnSessionError(
3938
+ SPAWN_SESSION_ERROR_CODES.SPAWN_NO_PID,
3939
+ "Failed to spawn terminal window - no PID returned"
3940
+ );
3941
+ return {
3942
+ type: spawnError.type,
3943
+ errorMessage: spawnError.errorMessage
3944
+ };
3945
+ }
3946
+ logger.debug(`[DAEMON RUN] Spawned terminal window process with PID ${terminalProcess.pid}`);
3947
+ const trackedSession = {
3948
+ startedBy: "daemon terminal window",
3949
+ happySessionId: options.sessionId,
3950
+ sessionIndex: null,
3951
+ skipDetachedManagedSessionArchive: true,
3952
+ pid: terminalProcess.pid,
3953
+ childProcess: terminalProcess,
3954
+ directoryCreated,
3955
+ message: directoryCreated ? `The path '${directory}' did not exist. We created a new folder and opened a terminal window there.` : `Opened a terminal window in '${directory}' to start the session.`
3956
+ };
3957
+ pidToTrackedSession.set(terminalProcess.pid, trackedSession);
3958
+ terminalProcess.on("exit", (code, signal) => {
3959
+ logger.debug(`[DAEMON RUN] Terminal launcher PID ${terminalProcess.pid} exited with code ${code}, signal ${signal}`);
3960
+ });
3961
+ terminalProcess.on("error", (error) => {
3962
+ logger.debug(`[DAEMON RUN] Terminal launcher process error:`, error);
3963
+ });
3964
+ terminalProcess.unref();
3965
+ const terminalAwaiterId = randomUUID();
3966
+ const launchStartedAt = Date.now();
3967
+ logger.debug(`[DAEMON RUN] Waiting for terminal window session webhook ${terminalAwaiterId}`);
3968
+ return new Promise((resolve) => {
3969
+ const timeout = setTimeout(() => {
3970
+ terminalLaunchAwaiters.delete(terminalAwaiterId);
3971
+ logger.debug(`[DAEMON RUN] Terminal window session webhook timeout for PID ${terminalProcess.pid}`);
3972
+ const spawnError = createSpawnSessionError(
3973
+ SPAWN_SESSION_ERROR_CODES.SESSION_WEBHOOK_TIMEOUT,
3974
+ `Terminal window session webhook timeout for PID ${terminalProcess.pid}`
3975
+ );
3976
+ resolve({
3977
+ type: spawnError.type,
3978
+ errorMessage: spawnError.errorMessage
3979
+ });
3980
+ }, sessionWebhookTimeoutMs);
3981
+ terminalLaunchAwaiters.set(terminalAwaiterId, {
3982
+ directory,
3983
+ agent: options.agent,
3984
+ startedAt: launchStartedAt,
3985
+ resolve: (result) => {
3986
+ clearTimeout(timeout);
3987
+ resolve(result);
3988
+ }
3989
+ });
3990
+ });
3991
+ }
3681
3992
  let tmuxSessionName = extraEnv.TMUX_SESSION_NAME;
3682
3993
  const tmuxRequested = tmuxSessionName !== void 0;
3683
3994
  const tmuxAvailable = tmuxRequested ? await isTmuxAvailable() : false;
@@ -4337,8 +4648,8 @@ async function install$1() {
4337
4648
  </dict>
4338
4649
  </plist>
4339
4650
  `);
4340
- writeFileSync(PLIST_FILE$1, plistContent);
4341
- chmodSync(PLIST_FILE$1, 420);
4651
+ writeFileSync$1(PLIST_FILE$1, plistContent);
4652
+ chmodSync$1(PLIST_FILE$1, 420);
4342
4653
  logger.info(`Created daemon plist at ${PLIST_FILE$1}`);
4343
4654
  execSync(`launchctl load ${PLIST_FILE$1}`, { stdio: "inherit" });
4344
4655
  logger.info("Daemon installed and started successfully");
@@ -5190,10 +5501,10 @@ async function handleConnectStatus() {
5190
5501
  }
5191
5502
  function updateLocalGeminiCredentials(tokens) {
5192
5503
  try {
5193
- const geminiDir = join$1(homedir(), ".gemini");
5504
+ const geminiDir = join$1(homedir$1(), ".gemini");
5194
5505
  const credentialsPath = join$1(geminiDir, "oauth_creds.json");
5195
5506
  if (!existsSync$1(geminiDir)) {
5196
- mkdirSync(geminiDir, { recursive: true });
5507
+ mkdirSync$1(geminiDir, { recursive: true });
5197
5508
  }
5198
5509
  const credentials = {
5199
5510
  access_token: tokens.access_token,
@@ -5203,7 +5514,7 @@ function updateLocalGeminiCredentials(tokens) {
5203
5514
  ...tokens.id_token && { id_token: tokens.id_token },
5204
5515
  ...tokens.expires_in && { expires_in: tokens.expires_in }
5205
5516
  };
5206
- writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), "utf-8");
5517
+ writeFileSync$1(credentialsPath, JSON.stringify(credentials, null, 2), "utf-8");
5207
5518
  console.log(chalk.gray(` Updated local credentials: ${credentialsPath}`));
5208
5519
  } catch (error) {
5209
5520
  console.log(chalk.yellow(` \u26A0\uFE0F Could not update local credentials: ${error}`));
@@ -6111,7 +6422,7 @@ function getProjectPath(workingDirectory, claudeConfigDirOverride) {
6111
6422
  const projectId = resolve$1(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
6112
6423
  const claudeConfigDirRaw = process.env.CLAUDE_CONFIG_DIR ?? "";
6113
6424
  const claudeConfigDirTrimmed = claudeConfigDirRaw.trim();
6114
- const claudeConfigDir = claudeConfigDirTrimmed ? claudeConfigDirTrimmed : join(homedir$1(), ".claude");
6425
+ const claudeConfigDir = claudeConfigDirTrimmed ? claudeConfigDirTrimmed : join(homedir(), ".claude");
6115
6426
  return join(claudeConfigDir, "projects", projectId);
6116
6427
  }
6117
6428
 
@@ -6176,7 +6487,7 @@ class ExitCodeError extends Error {
6176
6487
  const claudeCliPath = resolve$1(join(projectPath(), "scripts", "claude_local_launcher.cjs"));
6177
6488
  async function claudeLocal(opts) {
6178
6489
  const projectDir = getProjectPath(opts.path);
6179
- mkdirSync$1(projectDir, { recursive: true });
6490
+ mkdirSync(projectDir, { recursive: true });
6180
6491
  const hasContinueFlag = opts.claudeArgs?.includes("--continue");
6181
6492
  const hasResumeFlag = opts.claudeArgs?.includes("--resume");
6182
6493
  const hasUserSessionControl = hasContinueFlag || hasResumeFlag;
@@ -9352,10 +9663,14 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9352
9663
  async () => {
9353
9664
  let timeoutHandle = null;
9354
9665
  try {
9666
+ const resumeSession = this.connection.resumeSession ?? this.connection.unstable_resumeSession;
9355
9667
  const result = await raceWithProcessExit(
9356
9668
  this.process,
9357
9669
  () => Promise.race([
9358
- (sessionOperation === "resume" ? this.connection.resumeSession(sessionRequest) : sessionOperation === "load" ? this.connection.loadSession(sessionRequest) : this.connection.newSession(sessionRequest)).then((res) => {
9670
+ (sessionOperation === "resume" ? resumeSession ? resumeSession(sessionRequest).then((response) => ({
9671
+ ...response,
9672
+ sessionId: requestedResumeSessionId
9673
+ })) : Promise.reject(new Error("ACP agent advertised session resume, but this SDK connection does not expose resumeSession.")) : sessionOperation === "load" ? this.connection.loadSession(sessionRequest) : this.connection.newSession(sessionRequest)).then((res) => {
9359
9674
  if (timeoutHandle) {
9360
9675
  clearTimeout(timeoutHandle);
9361
9676
  timeoutHandle = null;
@@ -9782,12 +10097,12 @@ function readGeminiLocalConfig() {
9782
10097
  let googleCloudProject = null;
9783
10098
  let googleCloudProjectEmail = null;
9784
10099
  const possiblePaths = [
9785
- join$1(homedir(), ".gemini", "oauth_creds.json"),
10100
+ join$1(homedir$1(), ".gemini", "oauth_creds.json"),
9786
10101
  // Main OAuth credentials file
9787
- join$1(homedir(), ".gemini", "config.json"),
9788
- join$1(homedir(), ".config", "gemini", "config.json"),
9789
- join$1(homedir(), ".gemini", "auth.json"),
9790
- join$1(homedir(), ".config", "gemini", "auth.json")
10102
+ join$1(homedir$1(), ".gemini", "config.json"),
10103
+ join$1(homedir$1(), ".config", "gemini", "config.json"),
10104
+ join$1(homedir$1(), ".gemini", "auth.json"),
10105
+ join$1(homedir$1(), ".config", "gemini", "auth.json")
9791
10106
  ];
9792
10107
  for (const configPath of possiblePaths) {
9793
10108
  if (existsSync$1(configPath)) {
@@ -9865,10 +10180,10 @@ function determineGeminiModel(explicitModel, localConfig) {
9865
10180
  }
9866
10181
  function saveGeminiModelToConfig(model) {
9867
10182
  try {
9868
- const configDir = join$1(homedir(), ".gemini");
10183
+ const configDir = join$1(homedir$1(), ".gemini");
9869
10184
  const configPath = join$1(configDir, "config.json");
9870
10185
  if (!existsSync$1(configDir)) {
9871
- mkdirSync(configDir, { recursive: true });
10186
+ mkdirSync$1(configDir, { recursive: true });
9872
10187
  }
9873
10188
  let config = {};
9874
10189
  if (existsSync$1(configPath)) {
@@ -9880,7 +10195,7 @@ function saveGeminiModelToConfig(model) {
9880
10195
  }
9881
10196
  }
9882
10197
  config.model = model;
9883
- writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
10198
+ writeFileSync$1(configPath, JSON.stringify(config, null, 2), "utf-8");
9884
10199
  logger.debug(`[Gemini] Saved model "${model}" to ${configPath}`);
9885
10200
  } catch (error) {
9886
10201
  logger.debug(`[Gemini] Failed to save model to config:`, error);
@@ -9888,10 +10203,10 @@ function saveGeminiModelToConfig(model) {
9888
10203
  }
9889
10204
  function saveGoogleCloudProjectToConfig(projectId, email) {
9890
10205
  try {
9891
- const configDir = join$1(homedir(), ".gemini");
10206
+ const configDir = join$1(homedir$1(), ".gemini");
9892
10207
  const configPath = join$1(configDir, "config.json");
9893
10208
  if (!existsSync$1(configDir)) {
9894
- mkdirSync(configDir, { recursive: true });
10209
+ mkdirSync$1(configDir, { recursive: true });
9895
10210
  }
9896
10211
  let config = {};
9897
10212
  if (existsSync$1(configPath)) {
@@ -9905,7 +10220,7 @@ function saveGoogleCloudProjectToConfig(projectId, email) {
9905
10220
  if (email) {
9906
10221
  config.googleCloudProjectEmail = email;
9907
10222
  }
9908
- writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
10223
+ writeFileSync$1(configPath, JSON.stringify(config, null, 2), "utf-8");
9909
10224
  logger.debug(`[Gemini] Saved Google Cloud Project "${projectId}"${email ? ` for ${email}` : ""} to ${configPath}`);
9910
10225
  } catch (error) {
9911
10226
  logger.debug(`[Gemini] Failed to save Google Cloud Project to config:`, error);
@@ -10410,7 +10725,7 @@ function copyCodexHomeEntry(sourcePath, destPath) {
10410
10725
  if (!existsSync(sourcePath)) {
10411
10726
  return;
10412
10727
  }
10413
- mkdirSync$1(dirname$1(destPath), { recursive: true });
10728
+ mkdirSync(dirname$1(destPath), { recursive: true });
10414
10729
  cpSync(sourcePath, destPath, {
10415
10730
  recursive: true,
10416
10731
  force: true,
@@ -10494,7 +10809,7 @@ function seedCodexSkillEntries(sourceSkillsDir, isolatedHomeDir, sourceLabel) {
10494
10809
  return;
10495
10810
  }
10496
10811
  const destSkillsDir = join(isolatedHomeDir, "skills");
10497
- mkdirSync$1(destSkillsDir, { recursive: true });
10812
+ mkdirSync(destSkillsDir, { recursive: true });
10498
10813
  for (const entryName of readdirSync(sourceSkillsDir)) {
10499
10814
  const sourceEntryPath = join(sourceSkillsDir, entryName);
10500
10815
  if (!shouldSeedCodexSkillEntry(sourceEntryPath)) {
@@ -10677,7 +10992,7 @@ function prepareCodexAcpEnvironment(overrides = {}, options = {}) {
10677
10992
  return { env };
10678
10993
  }
10679
10994
  }
10680
- const sourceHomeDir = options.sourceHomeDir ?? join(homedir$1(), ".codex");
10995
+ const sourceHomeDir = options.sourceHomeDir ?? join(homedir(), ".codex");
10681
10996
  const bundledSkillsDir = options.bundledSkillsDir ?? join(projectPath(), "skills");
10682
10997
  if (shouldUseSourceCodexHomeForMutableAuth(sourceHomeDir)) {
10683
10998
  logger.debug("[codex] Using source CODEX_HOME for mutable Codex auth credentials");
@@ -10689,7 +11004,7 @@ function prepareCodexAcpEnvironment(overrides = {}, options = {}) {
10689
11004
  }
10690
11005
  const tempDirFactory = options.tempDirFactory ?? mkdtempSync;
10691
11006
  const isolatedHomeDir = tempDirFactory(join(tmpdir(), "happy-codex-home-"));
10692
- mkdirSync$1(isolatedHomeDir, { recursive: true });
11007
+ mkdirSync(isolatedHomeDir, { recursive: true });
10693
11008
  seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir, options.resumeSessionId, platform);
10694
11009
  env.CODEX_HOME = isolatedHomeDir;
10695
11010
  return {
@@ -10859,7 +11174,7 @@ function getGlobalClaudeVersion() {
10859
11174
  const output = execSync$1("claude --version", {
10860
11175
  encoding: "utf8",
10861
11176
  stdio: ["pipe", "pipe", "pipe"],
10862
- cwd: homedir$1(),
11177
+ cwd: homedir(),
10863
11178
  env: cleanEnv,
10864
11179
  windowsHide: true
10865
11180
  }).trim();
@@ -10896,7 +11211,7 @@ function getCleanEnv() {
10896
11211
  return env;
10897
11212
  }
10898
11213
  function findGlobalClaudePath() {
10899
- const homeDir = homedir$1();
11214
+ const homeDir = homedir();
10900
11215
  const cleanEnv = getCleanEnv();
10901
11216
  try {
10902
11217
  execSync$1("claude --version", {
@@ -12176,14 +12491,14 @@ var launch = /*#__PURE__*/Object.freeze({
12176
12491
  const unifiedProviderExecutors = {
12177
12492
  claude: async (opts) => {
12178
12493
  const claudeOptions = opts.claudeOptions ?? {};
12179
- const { runClaude } = await import('./runClaude-CFeIMCY2.mjs');
12494
+ const { runClaude } = await import('./runClaude-D3CBLW5o.mjs');
12180
12495
  await runClaude(opts.credentials, {
12181
12496
  ...claudeOptions,
12182
12497
  startingMode: claudeOptions.startingMode ?? (claudeOptions.startedBy === "daemon" ? "remote" : void 0)
12183
12498
  });
12184
12499
  },
12185
12500
  codex: async (opts) => {
12186
- const { runCodex } = await import('./runCodex-ByjUfTyr.mjs');
12501
+ const { runCodex } = await import('./runCodex-DqzdgDwZ.mjs');
12187
12502
  await runCodex({
12188
12503
  credentials: opts.credentials,
12189
12504
  startedBy: opts.startedBy,
@@ -12192,7 +12507,7 @@ const unifiedProviderExecutors = {
12192
12507
  });
12193
12508
  },
12194
12509
  gemini: async (opts) => {
12195
- const { runGemini } = await import('./runGemini-CihCRgcR.mjs');
12510
+ const { runGemini } = await import('./runGemini-UZuiKe59.mjs');
12196
12511
  await runGemini({
12197
12512
  credentials: opts.credentials,
12198
12513
  startedBy: opts.startedBy
@@ -12275,7 +12590,7 @@ function shouldRunMainClaudeFlow(opts) {
12275
12590
  return;
12276
12591
  } else if (subcommand === "runtime") {
12277
12592
  if (args[1] === "providers") {
12278
- const { renderRuntimeProviders } = await import('./command-umgXYSY2.mjs');
12593
+ const { renderRuntimeProviders } = await import('./command-BzPI4N1n.mjs');
12279
12594
  console.log(renderRuntimeProviders());
12280
12595
  return;
12281
12596
  }
@@ -12481,8 +12796,8 @@ function shouldRunMainClaudeFlow(opts) {
12481
12796
  const projectId = args[3];
12482
12797
  try {
12483
12798
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
12484
- const { readCredentials: readCredentials2 } = await import('./api-DTSpLLTK.mjs').then(function (n) { return n.Y; });
12485
- const { ApiClient: ApiClient2 } = await import('./api-DTSpLLTK.mjs').then(function (n) { return n.Z; });
12799
+ const { readCredentials: readCredentials2 } = await import('./api-CSjP-Z3Y.mjs').then(function (n) { return n.Y; });
12800
+ const { ApiClient: ApiClient2 } = await import('./api-CSjP-Z3Y.mjs').then(function (n) { return n.Z; });
12486
12801
  let userEmail = void 0;
12487
12802
  try {
12488
12803
  const credentials = await readCredentials2();