happy-imou-cloud 2.1.47 → 2.1.49

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-KXIi0QF_.mjs → BaseReasoningProcessor-CAVeOdyo.mjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-CBbzF7oj.cjs → BaseReasoningProcessor-Dn9NcoHz.cjs} +2 -2
  3. package/dist/{ProviderSelectionHandler-CJLlwlAu.cjs → ProviderSelectionHandler-BJJc7qOR.cjs} +2 -2
  4. package/dist/{ProviderSelectionHandler-DzYObYrV.mjs → ProviderSelectionHandler-DIYidT13.mjs} +2 -2
  5. package/dist/{api-CVuTajTL.cjs → api-D7nAeZi7.cjs} +3 -3
  6. package/dist/{api-D3vYIva3.mjs → api-DnqaNvyV.mjs} +3 -3
  7. package/dist/{command-fcJ-4Yq3.mjs → command-CzfRRhVe.mjs} +2 -2
  8. package/dist/{command-BZRQuZsh.cjs → command-VcH4hbhi.cjs} +2 -2
  9. package/dist/{index-Cp1I5I3U.mjs → index-7Z93BoVn.mjs} +378 -33
  10. package/dist/{index-CyW9A7hx.cjs → index-xa1kwZoj.cjs} +377 -32
  11. package/dist/index.cjs +2 -2
  12. package/dist/index.mjs +2 -2
  13. package/dist/lib.cjs +1 -1
  14. package/dist/lib.d.cts +88 -86
  15. package/dist/lib.d.mts +88 -86
  16. package/dist/lib.mjs +1 -1
  17. package/dist/{registerKillSessionHandler-8C_Wrgor.cjs → registerKillSessionHandler-CfCya6si.cjs} +2 -2
  18. package/dist/{registerKillSessionHandler-OhhMUuCQ.mjs → registerKillSessionHandler-DLDg2EES.mjs} +2 -2
  19. package/dist/{runClaude-CfdT_ccS.cjs → runClaude-BBGNmGj6.cjs} +4 -4
  20. package/dist/{runClaude-BviM1Wl5.mjs → runClaude-zCwRhpOw.mjs} +4 -4
  21. package/dist/{runCodex-Dx3osc7U.mjs → runCodex-BbgLVjb9.mjs} +80 -11
  22. package/dist/{runCodex-B-t0yy4k.cjs → runCodex-jUU6U2tZ.cjs} +80 -11
  23. package/dist/{runGemini-DZ5-uzB9.cjs → runGemini-C0NT8MHK.cjs} +4 -4
  24. package/dist/{runGemini-CnJ75Q--.mjs → runGemini-DcwNsudA.mjs} +4 -4
  25. package/package.json +1 -1
@@ -1,5 +1,5 @@
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-D3vYIva3.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-DnqaNvyV.mjs';
3
3
  import { z } from 'zod';
4
4
  import fs, { writeFile as writeFile$1, rename, unlink as unlink$1 } from 'fs/promises';
5
5
  import os$1, { homedir as homedir$1 } from 'os';
@@ -10,18 +10,18 @@ import qrcode from 'qrcode-terminal';
10
10
  import { writeFile, unlink, readdir, readFile, mkdir } from 'node:fs/promises';
11
11
  import { createRequire } from 'node:module';
12
12
  import os, { tmpdir, homedir } from 'node:os';
13
- import path, { join, resolve as resolve$1, dirname as dirname$1, normalize, isAbsolute, delimiter, relative, basename } from 'node:path';
13
+ import path, { join, delimiter, resolve as resolve$1, dirname as dirname$1, normalize, isAbsolute, relative, basename } from 'node:path';
14
14
  import open from 'open';
15
15
  import React, { useState } from 'react';
16
16
  import { useInput, Box, Text, render } from 'ink';
17
17
  import { spawn, execSync, exec } from 'child_process';
18
18
  import { dirname, resolve, join as join$1 } from 'path';
19
19
  import { fileURLToPath } from 'url';
20
- import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync as writeFileSync$1, chmodSync, unlinkSync as unlinkSync$1, mkdirSync as mkdirSync$1 } 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';
21
21
  import { execFileSync, spawn as spawn$2, execSync as execSync$1 } from 'node:child_process';
22
22
  import psList from 'ps-list';
23
23
  import spawn$1 from 'cross-spawn';
24
- import fs$1, { existsSync, readFileSync, readdirSync, statSync, unlinkSync, mkdirSync, writeFileSync, cpSync, rmSync, mkdtempSync, realpathSync } from 'node:fs';
24
+ import fs$1, { existsSync, readFileSync, readdirSync, statSync, mkdtempSync, writeFileSync, chmodSync, unlinkSync, mkdirSync, cpSync, rmSync, realpathSync } from 'node:fs';
25
25
  import fastify from 'fastify';
26
26
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
27
27
  import { randomUUID as randomUUID$1, randomBytes as randomBytes$1, createHash } from 'crypto';
@@ -1566,7 +1566,8 @@ function startDaemonControlServer({
1566
1566
  body: z.object({
1567
1567
  directory: z.string(),
1568
1568
  sessionId: z.string().optional(),
1569
- agent: z.enum(["claude", "codex", "gemini"]).optional()
1569
+ agent: z.enum(["claude", "codex", "gemini"]).optional(),
1570
+ launchMode: z.enum(["background", "terminalWindow", "localTerminal"]).optional()
1570
1571
  }),
1571
1572
  response: {
1572
1573
  200: z.object({
@@ -1587,9 +1588,9 @@ function startDaemonControlServer({
1587
1588
  }
1588
1589
  }
1589
1590
  }, async (request, reply) => {
1590
- const { directory, sessionId, agent } = request.body;
1591
- logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}, agent=${agent || "claude"}`);
1592
- 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 });
1593
1594
  switch (result.type) {
1594
1595
  case "success":
1595
1596
  if (!result.sessionId) {
@@ -2333,20 +2334,37 @@ function resolveDaemonSpawnAgent(agent) {
2333
2334
  throw new Error(`Unsupported agent type: '${agent}'. Please update your CLI to the latest version.`);
2334
2335
  }
2335
2336
  }
2336
- 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";
2341
+ const resolvedAgent = resolveDaemonSpawnAgent(agent);
2337
2342
  const args = [
2338
- resolveDaemonSpawnAgent(agent),
2343
+ resolvedAgent,
2339
2344
  "--happy-starting-mode",
2340
- "remote",
2345
+ startingMode,
2341
2346
  "--started-by",
2342
- "daemon"
2347
+ startedBy
2343
2348
  ];
2344
- const providerSessionId = typeof resume?.providerSessionId === "string" ? resume.providerSessionId.trim() : "";
2345
- if (providerSessionId.length > 0) {
2349
+ const providerSessionId = typeof options.resume?.providerSessionId === "string" ? options.resume.providerSessionId.trim() : "";
2350
+ if (providerSessionId.length > 0 && supportsProviderResumeArg(resolvedAgent)) {
2346
2351
  args.push("--resume", providerSessionId);
2347
2352
  }
2348
2353
  return args;
2349
2354
  }
2355
+ function supportsProviderResumeArg(agent) {
2356
+ return agent === "claude" || agent === "codex";
2357
+ }
2358
+ function buildTerminalWindowSpawnArgs(agent, resume) {
2359
+ return buildDaemonSpawnArgs(agent, {
2360
+ resume,
2361
+ startingMode: "local",
2362
+ startedBy: "terminal"
2363
+ });
2364
+ }
2365
+ function isLegacyResumeOptions(value) {
2366
+ return Boolean(value && "providerSessionId" in value);
2367
+ }
2350
2368
 
2351
2369
  const SPAWN_SESSION_ERROR_CODES = {
2352
2370
  INVALID_REQUEST: "INVALID_REQUEST",
@@ -2409,6 +2427,157 @@ function buildDaemonChildEnv(baseEnv, extraEnv) {
2409
2427
  return childEnv;
2410
2428
  }
2411
2429
 
2430
+ function quotePosix(value) {
2431
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
2432
+ }
2433
+ function quoteAppleScriptString(value) {
2434
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
2435
+ }
2436
+ function quoteWindowsCmd(value) {
2437
+ return `"${value.replace(/(["^&|<>()%])/g, "^$1")}"`;
2438
+ }
2439
+ function buildRuntimeInvocation(args, platform, entrypointOverride) {
2440
+ const projectRoot = projectPath();
2441
+ const entrypoint = entrypointOverride || join(projectRoot, "dist", "index.mjs");
2442
+ const runtime = isBun() ? "bun" : "node";
2443
+ const runtimeArgs = ["--no-warnings", "--no-deprecation", entrypoint, ...args];
2444
+ const commandParts = [runtime, ...runtimeArgs];
2445
+ if (platform === "win32") {
2446
+ return commandParts.map(quoteWindowsCmd).join(" ");
2447
+ }
2448
+ return commandParts.map(quotePosix).join(" ");
2449
+ }
2450
+ function buildUserFacingPreview(args) {
2451
+ const agent = args[0];
2452
+ if (agent === "claude" || agent === "codex" || agent === "gemini") {
2453
+ return `hicloud ${agent}`;
2454
+ }
2455
+ return `hicloud ${args.join(" ")}`.trim();
2456
+ }
2457
+ function buildPathWithProjectBin(env, platform) {
2458
+ const binPath = join(projectPath(), "node_modules", ".bin");
2459
+ const pathDelimiter = platform === "win32" ? ";" : delimiter;
2460
+ const currentPath = env?.PATH || env?.Path || process.env.PATH || "";
2461
+ return currentPath ? `${binPath}${pathDelimiter}${currentPath}` : binPath;
2462
+ }
2463
+ function isValidEnvironmentVariableName(name) {
2464
+ return /^[A-Za-z_][A-Za-z0-9_]*$/.test(name);
2465
+ }
2466
+ function escapeWindowsBatchSetValue(value) {
2467
+ return value.replace(/\r?\n/g, "").replace(/%/g, "%%");
2468
+ }
2469
+ function collectLaunchEnv(env, platform) {
2470
+ const result = {};
2471
+ for (const [key, value] of Object.entries(env || {})) {
2472
+ if (typeof value === "string" && isValidEnvironmentVariableName(key)) {
2473
+ result[key] = value;
2474
+ }
2475
+ }
2476
+ result.PATH = buildPathWithProjectBin(env, platform);
2477
+ return result;
2478
+ }
2479
+ function buildTerminalLaunchScriptContent(options) {
2480
+ const platform = options.platform || process.platform;
2481
+ const launchEnv = collectLaunchEnv(options.env, platform);
2482
+ const preview = buildUserFacingPreview(options.args);
2483
+ const runtimeInvocation = buildRuntimeInvocation(options.args, platform, options.entrypoint);
2484
+ if (platform === "win32") {
2485
+ const envLines2 = Object.entries(launchEnv).map(([key, value]) => `set "${key}=${escapeWindowsBatchSetValue(value)}"`).join("\r\n");
2486
+ return [
2487
+ "@echo off",
2488
+ "setlocal",
2489
+ envLines2,
2490
+ `cd /d ${quoteWindowsCmd(options.cwd)}`,
2491
+ `echo $ ${preview}`,
2492
+ runtimeInvocation,
2493
+ "echo.",
2494
+ "echo Happy session command exited. You can close this window.",
2495
+ 'del "%~f0" >nul 2>nul',
2496
+ "endlocal",
2497
+ ""
2498
+ ].join("\r\n");
2499
+ }
2500
+ const envLines = Object.entries(launchEnv).map(([key, value]) => `export ${key}=${quotePosix(value)}`).join("\n");
2501
+ return [
2502
+ "#!/usr/bin/env bash",
2503
+ "set +e",
2504
+ 'rm -f "$0" >/dev/null 2>&1 || true',
2505
+ envLines,
2506
+ `cd ${quotePosix(options.cwd)} || exit $?`,
2507
+ `echo ${quotePosix(`$ ${preview}`)}`,
2508
+ runtimeInvocation,
2509
+ "status=$?",
2510
+ "echo",
2511
+ 'echo "Happy session command exited with status ${status}. You can close this window."',
2512
+ 'exec "${SHELL:-bash}" -l',
2513
+ ""
2514
+ ].join("\n");
2515
+ }
2516
+ function createTerminalLaunchScript(options) {
2517
+ if (options.scriptPath) {
2518
+ return options.scriptPath;
2519
+ }
2520
+ const platform = options.platform || process.platform;
2521
+ const scriptDirectory = mkdtempSync(join(tmpdir(), "happy-terminal-launch-"));
2522
+ const scriptPath = join(scriptDirectory, platform === "win32" ? "launch.cmd" : "launch.sh");
2523
+ writeFileSync(scriptPath, buildTerminalLaunchScriptContent({ ...options, platform }), { encoding: "utf8", mode: 448 });
2524
+ if (platform !== "win32") {
2525
+ chmodSync(scriptPath, 448);
2526
+ }
2527
+ return scriptPath;
2528
+ }
2529
+ function buildTerminalWindowLaunchCommand(options) {
2530
+ const platform = options.platform || process.platform;
2531
+ const scriptPath = createTerminalLaunchScript({ ...options, platform });
2532
+ const preview = buildUserFacingPreview(options.args);
2533
+ if (platform === "win32") {
2534
+ return {
2535
+ command: "cmd.exe",
2536
+ args: ["/d", "/s", "/c", `start "" cmd.exe /d /s /k ${quoteWindowsCmd(scriptPath)}`],
2537
+ options: {
2538
+ cwd: options.cwd,
2539
+ detached: true,
2540
+ stdio: "ignore",
2541
+ env: options.env,
2542
+ windowsHide: false
2543
+ },
2544
+ preview,
2545
+ scriptPath
2546
+ };
2547
+ }
2548
+ if (platform === "darwin") {
2549
+ const appleScript = `tell application "Terminal" to do script ${quoteAppleScriptString(`bash ${quotePosix(scriptPath)}`)}`;
2550
+ return {
2551
+ command: "osascript",
2552
+ args: ["-e", appleScript],
2553
+ options: {
2554
+ cwd: options.cwd,
2555
+ detached: true,
2556
+ stdio: "ignore",
2557
+ env: options.env
2558
+ },
2559
+ preview,
2560
+ scriptPath
2561
+ };
2562
+ }
2563
+ return {
2564
+ command: "x-terminal-emulator",
2565
+ args: ["-e", "bash", scriptPath],
2566
+ options: {
2567
+ cwd: options.cwd,
2568
+ detached: true,
2569
+ stdio: "ignore",
2570
+ env: options.env
2571
+ },
2572
+ preview,
2573
+ scriptPath
2574
+ };
2575
+ }
2576
+ function spawnHappyCLIInTerminalWindow(options) {
2577
+ const launchCommand = buildTerminalWindowLaunchCommand(options);
2578
+ return spawn$2(launchCommand.command, launchCommand.args, launchCommand.options);
2579
+ }
2580
+
2412
2581
  const DIFFERENT_DAEMON_RUNNING_MESSAGE = "A different daemon was started without killing us. We should kill ourselves.";
2413
2582
  function pruneStaleTrackedSessions({
2414
2583
  trackedSessionPids,
@@ -3566,6 +3735,28 @@ async function startDaemon() {
3566
3735
  let api = null;
3567
3736
  const pidToTrackedSession = /* @__PURE__ */ new Map();
3568
3737
  const pidToAwaiter = /* @__PURE__ */ new Map();
3738
+ const terminalLaunchAwaiters = /* @__PURE__ */ new Map();
3739
+ const normalizePathForSessionMatch = (value) => (value || "").trim().replace(/[\\/]+$/, "");
3740
+ const resolveTerminalLaunchAwaiter = (sessionId, sessionMetadata) => {
3741
+ const reportedDirectory = normalizePathForSessionMatch(sessionMetadata.path);
3742
+ const reportedFlavor = resolveRecoverySpawnAgent(sessionMetadata.flavor);
3743
+ const now = Date.now();
3744
+ for (const [awaiterId, awaiter] of terminalLaunchAwaiters.entries()) {
3745
+ if (awaiter.startedAt - 5e3 > now) {
3746
+ continue;
3747
+ }
3748
+ const directoryMatches = normalizePathForSessionMatch(awaiter.directory) === reportedDirectory;
3749
+ const agentMatches = !awaiter.agent || !reportedFlavor || awaiter.agent === reportedFlavor;
3750
+ if (!directoryMatches || !agentMatches) {
3751
+ continue;
3752
+ }
3753
+ terminalLaunchAwaiters.delete(awaiterId);
3754
+ awaiter.resolve({ type: "success", sessionId });
3755
+ logger.debug(`[DAEMON RUN] Resolved terminal window session awaiter ${awaiterId} for session ${sessionId}`);
3756
+ return true;
3757
+ }
3758
+ return false;
3759
+ };
3569
3760
  const getCurrentChildren = () => Array.from(pidToTrackedSession.values());
3570
3761
  let userScopedObserver = null;
3571
3762
  const removeTrackedSession = (pid, archiveReason) => {
@@ -3614,6 +3805,7 @@ async function startDaemon() {
3614
3805
  };
3615
3806
  pidToTrackedSession.set(pid, trackedSession);
3616
3807
  logger.debug(`[DAEMON RUN] Registered externally-started session ${sessionId}`);
3808
+ resolveTerminalLaunchAwaiter(sessionId, sessionMetadata);
3617
3809
  }
3618
3810
  };
3619
3811
  const spawnSession = async (options) => {
@@ -3723,6 +3915,84 @@ async function startDaemon() {
3723
3915
  errorMessage: spawnError.errorMessage
3724
3916
  };
3725
3917
  }
3918
+ if (options.launchMode === "terminalWindow" || options.launchMode === "localTerminal") {
3919
+ logger.debug(`[DAEMON RUN] Using visible terminal window spawning`);
3920
+ let args;
3921
+ try {
3922
+ args = buildTerminalWindowSpawnArgs(options.agent, options.resume);
3923
+ } catch (error) {
3924
+ const spawnError = createSpawnSessionError(
3925
+ SPAWN_SESSION_ERROR_CODES.INVALID_REQUEST,
3926
+ error instanceof Error ? error.message : String(error)
3927
+ );
3928
+ return {
3929
+ type: spawnError.type,
3930
+ errorMessage: spawnError.errorMessage
3931
+ };
3932
+ }
3933
+ const terminalEnv = buildDaemonChildEnv(process.env, extraEnv);
3934
+ const terminalProcess = spawnHappyCLIInTerminalWindow({
3935
+ cwd: directory,
3936
+ args,
3937
+ env: terminalEnv
3938
+ });
3939
+ if (!terminalProcess.pid) {
3940
+ logger.debug("[DAEMON RUN] Failed to spawn terminal window - no PID returned");
3941
+ const spawnError = createSpawnSessionError(
3942
+ SPAWN_SESSION_ERROR_CODES.SPAWN_NO_PID,
3943
+ "Failed to spawn terminal window - no PID returned"
3944
+ );
3945
+ return {
3946
+ type: spawnError.type,
3947
+ errorMessage: spawnError.errorMessage
3948
+ };
3949
+ }
3950
+ logger.debug(`[DAEMON RUN] Spawned terminal window process with PID ${terminalProcess.pid}`);
3951
+ const trackedSession = {
3952
+ startedBy: "daemon terminal window",
3953
+ happySessionId: options.sessionId,
3954
+ sessionIndex: null,
3955
+ skipDetachedManagedSessionArchive: true,
3956
+ pid: terminalProcess.pid,
3957
+ childProcess: terminalProcess,
3958
+ directoryCreated,
3959
+ 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.`
3960
+ };
3961
+ pidToTrackedSession.set(terminalProcess.pid, trackedSession);
3962
+ terminalProcess.on("exit", (code, signal) => {
3963
+ logger.debug(`[DAEMON RUN] Terminal launcher PID ${terminalProcess.pid} exited with code ${code}, signal ${signal}`);
3964
+ });
3965
+ terminalProcess.on("error", (error) => {
3966
+ logger.debug(`[DAEMON RUN] Terminal launcher process error:`, error);
3967
+ });
3968
+ terminalProcess.unref();
3969
+ const terminalAwaiterId = randomUUID();
3970
+ const launchStartedAt = Date.now();
3971
+ logger.debug(`[DAEMON RUN] Waiting for terminal window session webhook ${terminalAwaiterId}`);
3972
+ return new Promise((resolve) => {
3973
+ const timeout = setTimeout(() => {
3974
+ terminalLaunchAwaiters.delete(terminalAwaiterId);
3975
+ logger.debug(`[DAEMON RUN] Terminal window session webhook timeout for PID ${terminalProcess.pid}`);
3976
+ const spawnError = createSpawnSessionError(
3977
+ SPAWN_SESSION_ERROR_CODES.SESSION_WEBHOOK_TIMEOUT,
3978
+ `Terminal window session webhook timeout for PID ${terminalProcess.pid}`
3979
+ );
3980
+ resolve({
3981
+ type: spawnError.type,
3982
+ errorMessage: spawnError.errorMessage
3983
+ });
3984
+ }, sessionWebhookTimeoutMs);
3985
+ terminalLaunchAwaiters.set(terminalAwaiterId, {
3986
+ directory,
3987
+ agent: options.agent,
3988
+ startedAt: launchStartedAt,
3989
+ resolve: (result) => {
3990
+ clearTimeout(timeout);
3991
+ resolve(result);
3992
+ }
3993
+ });
3994
+ });
3995
+ }
3726
3996
  let tmuxSessionName = extraEnv.TMUX_SESSION_NAME;
3727
3997
  const tmuxRequested = tmuxSessionName !== void 0;
3728
3998
  const tmuxAvailable = tmuxRequested ? await isTmuxAvailable() : false;
@@ -4383,7 +4653,7 @@ async function install$1() {
4383
4653
  </plist>
4384
4654
  `);
4385
4655
  writeFileSync$1(PLIST_FILE$1, plistContent);
4386
- chmodSync(PLIST_FILE$1, 420);
4656
+ chmodSync$1(PLIST_FILE$1, 420);
4387
4657
  logger.info(`Created daemon plist at ${PLIST_FILE$1}`);
4388
4658
  execSync(`launchctl load ${PLIST_FILE$1}`, { stdio: "inherit" });
4389
4659
  logger.info("Daemon installed and started successfully");
@@ -8795,6 +9065,69 @@ class AcpBackend {
8795
9065
  }
8796
9066
  return resolvePostPromptNoUpdatesTimeoutMs(this.transport);
8797
9067
  }
9068
+ getResponseWaitTimeoutMs(timeoutMs) {
9069
+ if (typeof timeoutMs === "number" && Number.isFinite(timeoutMs) && timeoutMs > 0) {
9070
+ return Math.trunc(timeoutMs);
9071
+ }
9072
+ return readPositiveIntegerEnv("HAPPY_ACP_RESPONSE_WAIT_TIMEOUT_MS") ?? readPositiveIntegerEnv("HAPPIER_ACP_RESPONSE_WAIT_TIMEOUT_MS") ?? resolveAcpResponseWaitTimeoutMs(this.sessionPreferences.timeoutProfile);
9073
+ }
9074
+ createPromptCompletionWatchdog(timeoutMs) {
9075
+ let timeoutHandle = null;
9076
+ let cancelled = false;
9077
+ const promise = new Promise((resolve, reject) => {
9078
+ const schedule = () => {
9079
+ if (cancelled) {
9080
+ return;
9081
+ }
9082
+ if (this.responseCompletionError) {
9083
+ reject(this.responseCompletionError);
9084
+ return;
9085
+ }
9086
+ if (!this.waitingForResponse) {
9087
+ resolve();
9088
+ return;
9089
+ }
9090
+ const lastProgressAt = this.responseLastProgressAt ?? Date.now();
9091
+ const elapsedMs = Math.max(0, Date.now() - lastProgressAt);
9092
+ const remainingMs = Math.max(1, timeoutMs - elapsedMs);
9093
+ timeoutHandle = setTimeout(() => {
9094
+ timeoutHandle = null;
9095
+ if (cancelled) {
9096
+ return;
9097
+ }
9098
+ if (this.responseCompletionError) {
9099
+ reject(this.responseCompletionError);
9100
+ return;
9101
+ }
9102
+ if (!this.waitingForResponse) {
9103
+ resolve();
9104
+ return;
9105
+ }
9106
+ const latestProgressAt = this.responseLastProgressAt ?? Date.now();
9107
+ const latestElapsedMs = Math.max(0, Date.now() - latestProgressAt);
9108
+ if (latestElapsedMs < timeoutMs) {
9109
+ schedule();
9110
+ return;
9111
+ }
9112
+ const timeoutLabel = formatToolCallTimeoutLimit(timeoutMs);
9113
+ const error = new Error(`Timeout waiting for Codex ACP prompt to complete after ${timeoutLabel} without response progress`);
9114
+ this.failPendingResponseWait(error);
9115
+ reject(error);
9116
+ }, remainingMs);
9117
+ };
9118
+ schedule();
9119
+ });
9120
+ return {
9121
+ promise,
9122
+ cancel: () => {
9123
+ cancelled = true;
9124
+ if (timeoutHandle) {
9125
+ clearTimeout(timeoutHandle);
9126
+ timeoutHandle = null;
9127
+ }
9128
+ }
9129
+ };
9130
+ }
8798
9131
  clearIdleTimeoutState() {
8799
9132
  if (this.idleTimeout) {
8800
9133
  clearTimeout(this.idleTimeout);
@@ -9397,10 +9730,14 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9397
9730
  async () => {
9398
9731
  let timeoutHandle = null;
9399
9732
  try {
9733
+ const resumeSession = this.connection.resumeSession ?? this.connection.unstable_resumeSession;
9400
9734
  const result = await raceWithProcessExit(
9401
9735
  this.process,
9402
9736
  () => Promise.race([
9403
- (sessionOperation === "resume" ? this.connection.resumeSession(sessionRequest) : sessionOperation === "load" ? this.connection.loadSession(sessionRequest) : this.connection.newSession(sessionRequest)).then((res) => {
9737
+ (sessionOperation === "resume" ? resumeSession ? resumeSession(sessionRequest).then((response) => ({
9738
+ ...response,
9739
+ sessionId: requestedResumeSessionId
9740
+ })) : 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) => {
9404
9741
  if (timeoutHandle) {
9405
9742
  clearTimeout(timeoutHandle);
9406
9743
  timeoutHandle = null;
@@ -9642,15 +9979,23 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9642
9979
  prompt: [contentBlock]
9643
9980
  };
9644
9981
  logger.debug(`[AcpBackend] Prompt request:`, JSON.stringify(promptRequest, null, 2));
9645
- await raceWithProcessExit(
9646
- this.process,
9647
- () => this.connection.prompt(promptRequest),
9648
- {
9649
- agentName: this.transport.agentName,
9650
- operationName: "prompt",
9651
- getStderrExcerpt: () => this.getRecentStderrExcerpt()
9652
- }
9653
- );
9982
+ const promptWatchdog = this.createPromptCompletionWatchdog(this.getResponseWaitTimeoutMs());
9983
+ try {
9984
+ await raceWithProcessExit(
9985
+ this.process,
9986
+ () => Promise.race([
9987
+ this.connection.prompt(promptRequest),
9988
+ promptWatchdog.promise
9989
+ ]),
9990
+ {
9991
+ agentName: this.transport.agentName,
9992
+ operationName: "prompt",
9993
+ getStderrExcerpt: () => this.getRecentStderrExcerpt()
9994
+ }
9995
+ );
9996
+ } finally {
9997
+ promptWatchdog.cancel();
9998
+ }
9654
9999
  logger.debug("[AcpBackend] Prompt request sent to ACP connection");
9655
10000
  if (this.waitingForResponse && this.activeToolCalls.size === 0 && this.sawSessionUpdateSincePrompt === false) {
9656
10001
  const noUpdatesTimeoutMs = this.getPostPromptNoUpdatesTimeoutMs();
@@ -9713,7 +10058,7 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9713
10058
  if (!this.waitingForResponse) {
9714
10059
  return;
9715
10060
  }
9716
- const effectiveTimeoutMs = timeoutMs ?? resolveAcpResponseWaitTimeoutMs(this.sessionPreferences.timeoutProfile);
10061
+ const effectiveTimeoutMs = this.getResponseWaitTimeoutMs(timeoutMs);
9717
10062
  return new Promise((resolve, reject) => {
9718
10063
  this.idleResolver = () => {
9719
10064
  this.idleResolver = null;
@@ -10047,7 +10392,7 @@ function registerGeminiAgent() {
10047
10392
  logger.debug("[Gemini] Registered with agent registry");
10048
10393
  }
10049
10394
 
10050
- const DEFAULT_CODEX_ACP_NPX_PACKAGE = "@zed-industries/codex-acp@0.10.0";
10395
+ const DEFAULT_CODEX_ACP_NPX_PACKAGE = "@zed-industries/codex-acp@0.14.0";
10051
10396
  function readFirstEnv(...names) {
10052
10397
  for (const name of names) {
10053
10398
  const raw = process.env[name];
@@ -12221,14 +12566,14 @@ var launch = /*#__PURE__*/Object.freeze({
12221
12566
  const unifiedProviderExecutors = {
12222
12567
  claude: async (opts) => {
12223
12568
  const claudeOptions = opts.claudeOptions ?? {};
12224
- const { runClaude } = await import('./runClaude-BviM1Wl5.mjs');
12569
+ const { runClaude } = await import('./runClaude-zCwRhpOw.mjs');
12225
12570
  await runClaude(opts.credentials, {
12226
12571
  ...claudeOptions,
12227
12572
  startingMode: claudeOptions.startingMode ?? (claudeOptions.startedBy === "daemon" ? "remote" : void 0)
12228
12573
  });
12229
12574
  },
12230
12575
  codex: async (opts) => {
12231
- const { runCodex } = await import('./runCodex-Dx3osc7U.mjs');
12576
+ const { runCodex } = await import('./runCodex-BbgLVjb9.mjs');
12232
12577
  await runCodex({
12233
12578
  credentials: opts.credentials,
12234
12579
  startedBy: opts.startedBy,
@@ -12237,7 +12582,7 @@ const unifiedProviderExecutors = {
12237
12582
  });
12238
12583
  },
12239
12584
  gemini: async (opts) => {
12240
- const { runGemini } = await import('./runGemini-CnJ75Q--.mjs');
12585
+ const { runGemini } = await import('./runGemini-DcwNsudA.mjs');
12241
12586
  await runGemini({
12242
12587
  credentials: opts.credentials,
12243
12588
  startedBy: opts.startedBy
@@ -12320,7 +12665,7 @@ function shouldRunMainClaudeFlow(opts) {
12320
12665
  return;
12321
12666
  } else if (subcommand === "runtime") {
12322
12667
  if (args[1] === "providers") {
12323
- const { renderRuntimeProviders } = await import('./command-fcJ-4Yq3.mjs');
12668
+ const { renderRuntimeProviders } = await import('./command-CzfRRhVe.mjs');
12324
12669
  console.log(renderRuntimeProviders());
12325
12670
  return;
12326
12671
  }
@@ -12526,8 +12871,8 @@ function shouldRunMainClaudeFlow(opts) {
12526
12871
  const projectId = args[3];
12527
12872
  try {
12528
12873
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
12529
- const { readCredentials: readCredentials2 } = await import('./api-D3vYIva3.mjs').then(function (n) { return n.Y; });
12530
- const { ApiClient: ApiClient2 } = await import('./api-D3vYIva3.mjs').then(function (n) { return n.Z; });
12874
+ const { readCredentials: readCredentials2 } = await import('./api-DnqaNvyV.mjs').then(function (n) { return n.Y; });
12875
+ const { ApiClient: ApiClient2 } = await import('./api-DnqaNvyV.mjs').then(function (n) { return n.Z; });
12531
12876
  let userEmail = void 0;
12532
12877
  try {
12533
12878
  const credentials = await readCredentials2();