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.
- package/dist/{BaseReasoningProcessor-KXIi0QF_.mjs → BaseReasoningProcessor-CAVeOdyo.mjs} +2 -2
- package/dist/{BaseReasoningProcessor-CBbzF7oj.cjs → BaseReasoningProcessor-Dn9NcoHz.cjs} +2 -2
- package/dist/{ProviderSelectionHandler-CJLlwlAu.cjs → ProviderSelectionHandler-BJJc7qOR.cjs} +2 -2
- package/dist/{ProviderSelectionHandler-DzYObYrV.mjs → ProviderSelectionHandler-DIYidT13.mjs} +2 -2
- package/dist/{api-CVuTajTL.cjs → api-D7nAeZi7.cjs} +3 -3
- package/dist/{api-D3vYIva3.mjs → api-DnqaNvyV.mjs} +3 -3
- package/dist/{command-fcJ-4Yq3.mjs → command-CzfRRhVe.mjs} +2 -2
- package/dist/{command-BZRQuZsh.cjs → command-VcH4hbhi.cjs} +2 -2
- package/dist/{index-Cp1I5I3U.mjs → index-7Z93BoVn.mjs} +378 -33
- package/dist/{index-CyW9A7hx.cjs → index-xa1kwZoj.cjs} +377 -32
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +88 -86
- package/dist/lib.d.mts +88 -86
- package/dist/lib.mjs +1 -1
- package/dist/{registerKillSessionHandler-8C_Wrgor.cjs → registerKillSessionHandler-CfCya6si.cjs} +2 -2
- package/dist/{registerKillSessionHandler-OhhMUuCQ.mjs → registerKillSessionHandler-DLDg2EES.mjs} +2 -2
- package/dist/{runClaude-CfdT_ccS.cjs → runClaude-BBGNmGj6.cjs} +4 -4
- package/dist/{runClaude-BviM1Wl5.mjs → runClaude-zCwRhpOw.mjs} +4 -4
- package/dist/{runCodex-Dx3osc7U.mjs → runCodex-BbgLVjb9.mjs} +80 -11
- package/dist/{runCodex-B-t0yy4k.cjs → runCodex-jUU6U2tZ.cjs} +80 -11
- package/dist/{runGemini-DZ5-uzB9.cjs → runGemini-C0NT8MHK.cjs} +4 -4
- package/dist/{runGemini-CnJ75Q--.mjs → runGemini-DcwNsudA.mjs} +4 -4
- 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-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
2343
|
+
resolvedAgent,
|
|
2339
2344
|
"--happy-starting-mode",
|
|
2340
|
-
|
|
2345
|
+
startingMode,
|
|
2341
2346
|
"--started-by",
|
|
2342
|
-
|
|
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" ?
|
|
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
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
|
|
9651
|
-
|
|
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 =
|
|
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.
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
12530
|
-
const { ApiClient: ApiClient2 } = await import('./api-
|
|
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();
|