happy-imou-cloud 2.1.47 → 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.
- package/dist/{BaseReasoningProcessor-CBbzF7oj.cjs → BaseReasoningProcessor-CKtDfihV.cjs} +2 -2
- package/dist/{BaseReasoningProcessor-KXIi0QF_.mjs → BaseReasoningProcessor-CM3JbXUC.mjs} +2 -2
- package/dist/{ProviderSelectionHandler-CJLlwlAu.cjs → ProviderSelectionHandler-BHKIBw4t.cjs} +2 -2
- package/dist/{ProviderSelectionHandler-DzYObYrV.mjs → ProviderSelectionHandler-vgZ2egD_.mjs} +2 -2
- package/dist/{api-D3vYIva3.mjs → api-CSjP-Z3Y.mjs} +3 -3
- package/dist/{api-CVuTajTL.cjs → api-eaGKJjMt.cjs} +3 -3
- package/dist/{command-fcJ-4Yq3.mjs → command-BzPI4N1n.mjs} +2 -2
- package/dist/{command-BZRQuZsh.cjs → command-DDoz1Eky.cjs} +2 -2
- package/dist/{index-Cp1I5I3U.mjs → index-BzsBo3_Z.mjs} +290 -20
- package/dist/{index-CyW9A7hx.cjs → index-C8X1VlHZ.cjs} +289 -19
- package/dist/index.cjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +2 -0
- package/dist/lib.d.mts +2 -0
- package/dist/lib.mjs +1 -1
- package/dist/{registerKillSessionHandler-OhhMUuCQ.mjs → registerKillSessionHandler-BHu-3hZQ.mjs} +2 -2
- package/dist/{registerKillSessionHandler-8C_Wrgor.cjs → registerKillSessionHandler-CLCYBgZX.cjs} +2 -2
- package/dist/{runClaude-CfdT_ccS.cjs → runClaude-BkUbXE2F.cjs} +4 -4
- package/dist/{runClaude-BviM1Wl5.mjs → runClaude-D3CBLW5o.mjs} +4 -4
- package/dist/{runCodex-B-t0yy4k.cjs → runCodex-CdgrZK7P.cjs} +29 -8
- package/dist/{runCodex-Dx3osc7U.mjs → runCodex-DqzdgDwZ.mjs} +29 -8
- package/dist/{runGemini-DZ5-uzB9.cjs → runGemini-BE05R24D.cjs} +4 -4
- package/dist/{runGemini-CnJ75Q--.mjs → runGemini-UZuiKe59.mjs} +4 -4
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
4
|
-
var persistence = require('./api-
|
|
3
|
+
var index = require('./index-C8X1VlHZ.cjs');
|
|
4
|
+
var persistence = require('./api-eaGKJjMt.cjs');
|
|
5
5
|
var node_events = require('node:events');
|
|
6
6
|
var node_crypto = require('node:crypto');
|
|
7
7
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as createSessionMetadata, p as publishSessionRegistration } from './index-
|
|
2
|
-
import { s as startOfflineReconnection, c as configuration, i as isAuthenticationRequiredError, l as logger } from './api-
|
|
1
|
+
import { a as createSessionMetadata, p as publishSessionRegistration } from './index-BzsBo3_Z.mjs';
|
|
2
|
+
import { s as startOfflineReconnection, c as configuration, i as isAuthenticationRequiredError, l as logger } from './api-CSjP-Z3Y.mjs';
|
|
3
3
|
import { EventEmitter } from 'node:events';
|
|
4
4
|
import { randomUUID } from 'node:crypto';
|
|
5
5
|
|
package/dist/{ProviderSelectionHandler-CJLlwlAu.cjs → ProviderSelectionHandler-BHKIBw4t.cjs}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var persistence = require('./api-
|
|
4
|
-
var registerKillSessionHandler = require('./registerKillSessionHandler-
|
|
3
|
+
var persistence = require('./api-eaGKJjMt.cjs');
|
|
4
|
+
var registerKillSessionHandler = require('./registerKillSessionHandler-CLCYBgZX.cjs');
|
|
5
5
|
|
|
6
6
|
async function runModeLoop(opts) {
|
|
7
7
|
let currentMode = opts.startingMode;
|
package/dist/{ProviderSelectionHandler-DzYObYrV.mjs → ProviderSelectionHandler-vgZ2egD_.mjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { l as logger } from './api-
|
|
2
|
-
import { g as getPendingInteractionTimeoutMs, I as INTERACTION_SUPERSEDED_ERROR, a as INTERACTION_TIMED_OUT_ERROR } from './registerKillSessionHandler-
|
|
1
|
+
import { l as logger } from './api-CSjP-Z3Y.mjs';
|
|
2
|
+
import { g as getPendingInteractionTimeoutMs, I as INTERACTION_SUPERSEDED_ERROR, a as INTERACTION_TIMED_OUT_ERROR } from './registerKillSessionHandler-BHu-3hZQ.mjs';
|
|
3
3
|
|
|
4
4
|
async function runModeLoop(opts) {
|
|
5
5
|
let currentMode = opts.startingMode;
|
|
@@ -18,7 +18,7 @@ import { spawn } from 'node:child_process';
|
|
|
18
18
|
import { Expo } from 'expo-server-sdk';
|
|
19
19
|
|
|
20
20
|
var name = "happy-imou-cloud";
|
|
21
|
-
var version = "2.1.
|
|
21
|
+
var version = "2.1.48";
|
|
22
22
|
var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
|
|
23
23
|
var author = "long.zhu";
|
|
24
24
|
var license = "MIT";
|
|
@@ -6198,12 +6198,12 @@ class ApiMachineClient {
|
|
|
6198
6198
|
requestShutdown
|
|
6199
6199
|
}) {
|
|
6200
6200
|
this.rpcHandlerManager.registerHandler("spawn-happy-session", async (params) => {
|
|
6201
|
-
const { directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, environmentVariables } = params || {};
|
|
6201
|
+
const { directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, launchMode, environmentVariables } = params || {};
|
|
6202
6202
|
logger.debug(`[API MACHINE] Spawning session with params: ${JSON.stringify(params)}`);
|
|
6203
6203
|
if (!directory) {
|
|
6204
6204
|
throw new Error("Directory is required");
|
|
6205
6205
|
}
|
|
6206
|
-
const result = await spawnSession({ directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, environmentVariables });
|
|
6206
|
+
const result = await spawnSession({ directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, launchMode, environmentVariables });
|
|
6207
6207
|
switch (result.type) {
|
|
6208
6208
|
case "success":
|
|
6209
6209
|
logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
|
|
@@ -38,7 +38,7 @@ function _interopNamespaceDefault(e) {
|
|
|
38
38
|
var z__namespace = /*#__PURE__*/_interopNamespaceDefault(z);
|
|
39
39
|
|
|
40
40
|
var name = "happy-imou-cloud";
|
|
41
|
-
var version = "2.1.
|
|
41
|
+
var version = "2.1.48";
|
|
42
42
|
var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
|
|
43
43
|
var author = "long.zhu";
|
|
44
44
|
var license = "MIT";
|
|
@@ -6218,12 +6218,12 @@ class ApiMachineClient {
|
|
|
6218
6218
|
requestShutdown
|
|
6219
6219
|
}) {
|
|
6220
6220
|
this.rpcHandlerManager.registerHandler("spawn-happy-session", async (params) => {
|
|
6221
|
-
const { directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, environmentVariables } = params || {};
|
|
6221
|
+
const { directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, launchMode, environmentVariables } = params || {};
|
|
6222
6222
|
logger.debug(`[API MACHINE] Spawning session with params: ${JSON.stringify(params)}`);
|
|
6223
6223
|
if (!directory) {
|
|
6224
6224
|
throw new Error("Directory is required");
|
|
6225
6225
|
}
|
|
6226
|
-
const result = await spawnSession({ directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, environmentVariables });
|
|
6226
|
+
const result = await spawnSession({ directory, sessionId, machineId, managedSessionTag, approvedNewDirectoryCreation, agent, token, resume, launchMode, environmentVariables });
|
|
6227
6227
|
switch (result.type) {
|
|
6228
6228
|
case "success":
|
|
6229
6229
|
logger.debug(`[API MACHINE] Spawned session ${result.sessionId}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createDefaultRuntimeShell } from './index-
|
|
1
|
+
import { c as createDefaultRuntimeShell } from './index-BzsBo3_Z.mjs';
|
|
2
2
|
import 'chalk';
|
|
3
|
-
import './api-
|
|
3
|
+
import './api-CSjP-Z3Y.mjs';
|
|
4
4
|
import 'axios';
|
|
5
5
|
import 'fs';
|
|
6
6
|
import 'node:fs';
|
|
@@ -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-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
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,33 @@ 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";
|
|
2337
2341
|
const args = [
|
|
2338
2342
|
resolveDaemonSpawnAgent(agent),
|
|
2339
2343
|
"--happy-starting-mode",
|
|
2340
|
-
|
|
2344
|
+
startingMode,
|
|
2341
2345
|
"--started-by",
|
|
2342
|
-
|
|
2346
|
+
startedBy
|
|
2343
2347
|
];
|
|
2344
|
-
const providerSessionId = typeof resume?.providerSessionId === "string" ? resume.providerSessionId.trim() : "";
|
|
2348
|
+
const providerSessionId = typeof options.resume?.providerSessionId === "string" ? options.resume.providerSessionId.trim() : "";
|
|
2345
2349
|
if (providerSessionId.length > 0) {
|
|
2346
2350
|
args.push("--resume", providerSessionId);
|
|
2347
2351
|
}
|
|
2348
2352
|
return args;
|
|
2349
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
|
+
}
|
|
2350
2364
|
|
|
2351
2365
|
const SPAWN_SESSION_ERROR_CODES = {
|
|
2352
2366
|
INVALID_REQUEST: "INVALID_REQUEST",
|
|
@@ -2409,6 +2423,157 @@ function buildDaemonChildEnv(baseEnv, extraEnv) {
|
|
|
2409
2423
|
return childEnv;
|
|
2410
2424
|
}
|
|
2411
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
|
+
|
|
2412
2577
|
const DIFFERENT_DAEMON_RUNNING_MESSAGE = "A different daemon was started without killing us. We should kill ourselves.";
|
|
2413
2578
|
function pruneStaleTrackedSessions({
|
|
2414
2579
|
trackedSessionPids,
|
|
@@ -3566,6 +3731,28 @@ async function startDaemon() {
|
|
|
3566
3731
|
let api = null;
|
|
3567
3732
|
const pidToTrackedSession = /* @__PURE__ */ new Map();
|
|
3568
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
|
+
};
|
|
3569
3756
|
const getCurrentChildren = () => Array.from(pidToTrackedSession.values());
|
|
3570
3757
|
let userScopedObserver = null;
|
|
3571
3758
|
const removeTrackedSession = (pid, archiveReason) => {
|
|
@@ -3614,6 +3801,7 @@ async function startDaemon() {
|
|
|
3614
3801
|
};
|
|
3615
3802
|
pidToTrackedSession.set(pid, trackedSession);
|
|
3616
3803
|
logger.debug(`[DAEMON RUN] Registered externally-started session ${sessionId}`);
|
|
3804
|
+
resolveTerminalLaunchAwaiter(sessionId, sessionMetadata);
|
|
3617
3805
|
}
|
|
3618
3806
|
};
|
|
3619
3807
|
const spawnSession = async (options) => {
|
|
@@ -3723,6 +3911,84 @@ async function startDaemon() {
|
|
|
3723
3911
|
errorMessage: spawnError.errorMessage
|
|
3724
3912
|
};
|
|
3725
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
|
+
}
|
|
3726
3992
|
let tmuxSessionName = extraEnv.TMUX_SESSION_NAME;
|
|
3727
3993
|
const tmuxRequested = tmuxSessionName !== void 0;
|
|
3728
3994
|
const tmuxAvailable = tmuxRequested ? await isTmuxAvailable() : false;
|
|
@@ -4383,7 +4649,7 @@ async function install$1() {
|
|
|
4383
4649
|
</plist>
|
|
4384
4650
|
`);
|
|
4385
4651
|
writeFileSync$1(PLIST_FILE$1, plistContent);
|
|
4386
|
-
chmodSync(PLIST_FILE$1, 420);
|
|
4652
|
+
chmodSync$1(PLIST_FILE$1, 420);
|
|
4387
4653
|
logger.info(`Created daemon plist at ${PLIST_FILE$1}`);
|
|
4388
4654
|
execSync(`launchctl load ${PLIST_FILE$1}`, { stdio: "inherit" });
|
|
4389
4655
|
logger.info("Daemon installed and started successfully");
|
|
@@ -9397,10 +9663,14 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
|
|
|
9397
9663
|
async () => {
|
|
9398
9664
|
let timeoutHandle = null;
|
|
9399
9665
|
try {
|
|
9666
|
+
const resumeSession = this.connection.resumeSession ?? this.connection.unstable_resumeSession;
|
|
9400
9667
|
const result = await raceWithProcessExit(
|
|
9401
9668
|
this.process,
|
|
9402
9669
|
() => Promise.race([
|
|
9403
|
-
(sessionOperation === "resume" ?
|
|
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) => {
|
|
9404
9674
|
if (timeoutHandle) {
|
|
9405
9675
|
clearTimeout(timeoutHandle);
|
|
9406
9676
|
timeoutHandle = null;
|
|
@@ -12221,14 +12491,14 @@ var launch = /*#__PURE__*/Object.freeze({
|
|
|
12221
12491
|
const unifiedProviderExecutors = {
|
|
12222
12492
|
claude: async (opts) => {
|
|
12223
12493
|
const claudeOptions = opts.claudeOptions ?? {};
|
|
12224
|
-
const { runClaude } = await import('./runClaude-
|
|
12494
|
+
const { runClaude } = await import('./runClaude-D3CBLW5o.mjs');
|
|
12225
12495
|
await runClaude(opts.credentials, {
|
|
12226
12496
|
...claudeOptions,
|
|
12227
12497
|
startingMode: claudeOptions.startingMode ?? (claudeOptions.startedBy === "daemon" ? "remote" : void 0)
|
|
12228
12498
|
});
|
|
12229
12499
|
},
|
|
12230
12500
|
codex: async (opts) => {
|
|
12231
|
-
const { runCodex } = await import('./runCodex-
|
|
12501
|
+
const { runCodex } = await import('./runCodex-DqzdgDwZ.mjs');
|
|
12232
12502
|
await runCodex({
|
|
12233
12503
|
credentials: opts.credentials,
|
|
12234
12504
|
startedBy: opts.startedBy,
|
|
@@ -12237,7 +12507,7 @@ const unifiedProviderExecutors = {
|
|
|
12237
12507
|
});
|
|
12238
12508
|
},
|
|
12239
12509
|
gemini: async (opts) => {
|
|
12240
|
-
const { runGemini } = await import('./runGemini-
|
|
12510
|
+
const { runGemini } = await import('./runGemini-UZuiKe59.mjs');
|
|
12241
12511
|
await runGemini({
|
|
12242
12512
|
credentials: opts.credentials,
|
|
12243
12513
|
startedBy: opts.startedBy
|
|
@@ -12320,7 +12590,7 @@ function shouldRunMainClaudeFlow(opts) {
|
|
|
12320
12590
|
return;
|
|
12321
12591
|
} else if (subcommand === "runtime") {
|
|
12322
12592
|
if (args[1] === "providers") {
|
|
12323
|
-
const { renderRuntimeProviders } = await import('./command-
|
|
12593
|
+
const { renderRuntimeProviders } = await import('./command-BzPI4N1n.mjs');
|
|
12324
12594
|
console.log(renderRuntimeProviders());
|
|
12325
12595
|
return;
|
|
12326
12596
|
}
|
|
@@ -12526,8 +12796,8 @@ function shouldRunMainClaudeFlow(opts) {
|
|
|
12526
12796
|
const projectId = args[3];
|
|
12527
12797
|
try {
|
|
12528
12798
|
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
|
|
12529
|
-
const { readCredentials: readCredentials2 } = await import('./api-
|
|
12530
|
-
const { ApiClient: ApiClient2 } = await import('./api-
|
|
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; });
|
|
12531
12801
|
let userEmail = void 0;
|
|
12532
12802
|
try {
|
|
12533
12803
|
const credentials = await readCredentials2();
|