happy-imou-cloud 2.0.0 → 2.0.2

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 (27) hide show
  1. package/dist/{BaseReasoningProcessor-BRCQXCZY.cjs → BaseReasoningProcessor-B6tJ_eL5.cjs} +96 -9
  2. package/dist/{BaseReasoningProcessor-BKLRCKTU.mjs → BaseReasoningProcessor-D8VhEbs2.mjs} +95 -10
  3. package/dist/{api-D7OK-mML.cjs → api-D2Njw9Im.cjs} +124 -6
  4. package/dist/{api-BGXYX0yH.mjs → api-MYhAGPLn.mjs} +122 -7
  5. package/dist/{command-G85giEAF.cjs → command-CVldr51S.cjs} +3 -3
  6. package/dist/{command-CnLtKtP-.mjs → command-nmK6O-ab.mjs} +3 -3
  7. package/dist/{index-C7Y0R-MI.mjs → index-B97L7qLD.mjs} +689 -229
  8. package/dist/{index-B_wlQBy2.cjs → index-Bg-YziG2.cjs} +691 -229
  9. package/dist/index.cjs +4 -4
  10. package/dist/index.mjs +4 -4
  11. package/dist/lib.cjs +1 -1
  12. package/dist/lib.d.cts +7 -0
  13. package/dist/lib.d.mts +7 -0
  14. package/dist/lib.mjs +1 -1
  15. package/dist/{persistence-DHgf1CTG.cjs → persistence-D_2GkJAO.cjs} +28 -6
  16. package/dist/{persistence-BA_unuca.mjs → persistence-Dkm7rm8k.mjs} +29 -7
  17. package/dist/{registerKillSessionHandler-C2-yHm1V.mjs → registerKillSessionHandler-5GbrO0FM.mjs} +6 -4
  18. package/dist/{registerKillSessionHandler-CLREXN11.cjs → registerKillSessionHandler-BAXmJQRt.cjs} +6 -4
  19. package/dist/{runClaude-CwAitpX-.cjs → runClaude-B-GNEkKg.cjs} +237 -45
  20. package/dist/{runClaude-uNC5Eym4.mjs → runClaude-Cii3R2Fv.mjs} +238 -46
  21. package/dist/{runCodex-B-05E-YZ.mjs → runCodex-C--ZwAhl.mjs} +636 -819
  22. package/dist/{runCodex-Cm0VTqw_.cjs → runCodex-CPHyGwj9.cjs} +639 -819
  23. package/dist/{runGemini-_biXvQAH.mjs → runGemini-CQp7Nuzn.mjs} +20 -16
  24. package/dist/{runGemini-CLWjwDYS.cjs → runGemini-DaDz1bzQ.cjs} +20 -16
  25. package/package.json +14 -15
  26. package/scripts/env-wrapper.cjs +11 -11
  27. package/scripts/setup-dev.cjs +4 -4
@@ -1,6 +1,6 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
- import { l as logger, e as encodeBase64, c as configuration, h as buildAuthenticatedHeaders, i as encodeBase64Url, f as delay, j as buildClientHeaders, k as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, A as ApiClient, m as getLatestDaemonLog } from './api-BGXYX0yH.mjs';
3
- import { readCredentials, readSettings, updateSettings, writeCredentialsLegacy, writeCredentialsDataKey, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-BA_unuca.mjs';
2
+ import { l as logger, e as encodeBase64, c as configuration, h as buildAuthenticatedHeaders, S as SigningBootstrapRequiredError, j as SIGNING_BOOTSTRAP_REQUIRED_MESSAGE, k as encodeBase64Url, f as delay, m as buildClientHeaders, n as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, A as ApiClient, o as getLatestDaemonLog } from './api-MYhAGPLn.mjs';
3
+ import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-Dkm7rm8k.mjs';
4
4
  import { z } from 'zod';
5
5
  import fs from 'fs/promises';
6
6
  import os, { homedir } from 'os';
@@ -12,7 +12,7 @@ import qrcode from 'qrcode-terminal';
12
12
  import { writeFile, unlink } from 'node:fs/promises';
13
13
  import { createRequire } from 'node:module';
14
14
  import os$1, { tmpdir, homedir as homedir$1 } from 'node:os';
15
- import path, { join, resolve as resolve$1, isAbsolute } from 'node:path';
15
+ import { join, resolve as resolve$1, isAbsolute, delimiter } from 'node:path';
16
16
  import open from 'open';
17
17
  import React, { useState } from 'react';
18
18
  import { useInput, Box, Text, render } from 'ink';
@@ -23,7 +23,7 @@ import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSy
23
23
  import { execFileSync, spawn as spawn$2 } from 'node:child_process';
24
24
  import psList from 'ps-list';
25
25
  import spawn$1 from 'cross-spawn';
26
- import fs$1, { existsSync, readFileSync, readdirSync, statSync, rmSync, mkdirSync as mkdirSync$1 } from 'node:fs';
26
+ import { existsSync, readFileSync, readdirSync, statSync, rmSync, mkdirSync as mkdirSync$1 } from 'node:fs';
27
27
  import fastify from 'fastify';
28
28
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
29
29
  import { createInterface } from 'node:readline';
@@ -219,6 +219,64 @@ const AuthSelector = ({ onSelect, onCancel }) => {
219
219
  })), /* @__PURE__ */ React.createElement(Box, { marginTop: 1 }, /* @__PURE__ */ React.createElement(Text, { dimColor: true }, "Use arrows or 1-2 to select, Enter to confirm")));
220
220
  };
221
221
 
222
+ async function ensureSigningCredentials(credentials, opts = {}) {
223
+ if (credentials.signing) {
224
+ return credentials;
225
+ }
226
+ try {
227
+ const response = await axios.post(`${configuration.serverUrl}/v1/auth/refresh`, {}, {
228
+ headers: buildAuthenticatedHeaders({
229
+ credentials,
230
+ method: "POST",
231
+ url: `${configuration.serverUrl}/v1/auth/refresh`,
232
+ body: {},
233
+ headers: {
234
+ "Content-Type": "application/json"
235
+ },
236
+ signRequest: false
237
+ })
238
+ });
239
+ if (!response.data?.success || !response.data?.token || !response.data?.signing) {
240
+ logger.debug("[AUTH] Signing bootstrap returned incomplete payload", response.data);
241
+ throw new SigningBootstrapRequiredError(SIGNING_BOOTSTRAP_REQUIRED_MESSAGE);
242
+ }
243
+ const upgradedCredentials = {
244
+ ...credentials,
245
+ token: response.data.token,
246
+ signing: response.data.signing
247
+ };
248
+ if (upgradedCredentials.encryption.type === "legacy") {
249
+ await writeCredentialsLegacy({
250
+ secret: upgradedCredentials.encryption.secret,
251
+ token: upgradedCredentials.token,
252
+ signing: upgradedCredentials.signing
253
+ });
254
+ } else {
255
+ await writeCredentialsDataKey({
256
+ publicKey: upgradedCredentials.encryption.publicKey,
257
+ machineKey: upgradedCredentials.encryption.machineKey,
258
+ token: upgradedCredentials.token,
259
+ signing: upgradedCredentials.signing
260
+ });
261
+ }
262
+ logger.debug("[AUTH] Signing credentials bootstrapped successfully");
263
+ return upgradedCredentials;
264
+ } catch (error) {
265
+ if (axios.isAxiosError(error) && error.response?.status === 401) {
266
+ logger.debug("[AUTH] Signing bootstrap rejected with 401");
267
+ throw new SigningBootstrapRequiredError(SIGNING_BOOTSTRAP_REQUIRED_MESSAGE);
268
+ }
269
+ if (error instanceof SigningBootstrapRequiredError) {
270
+ throw error;
271
+ }
272
+ logger.debug("[AUTH] Failed to bootstrap signing credentials", error);
273
+ if (opts.failFast) {
274
+ throw new SigningBootstrapRequiredError(SIGNING_BOOTSTRAP_REQUIRED_MESSAGE);
275
+ }
276
+ return credentials;
277
+ }
278
+ }
279
+
222
280
  function isNonInteractive() {
223
281
  return !process.stdin.isTTY || !process.stdout.isTTY;
224
282
  }
@@ -520,7 +578,7 @@ async function authAndSetupMachineIfNeeded() {
520
578
  } else {
521
579
  logger.debug("[AUTH] Using existing credentials");
522
580
  }
523
- credentials = await ensureSigningCredentials(credentials);
581
+ credentials = await ensureSigningCredentials(credentials, { failFast: newAuth });
524
582
  const currentSettings = await readSettings();
525
583
  const settings = newAuth || !currentSettings.machineId ? await updateSettings(async (s) => ({
526
584
  ...s,
@@ -529,53 +587,6 @@ async function authAndSetupMachineIfNeeded() {
529
587
  logger.debug(`[AUTH] Machine ID: ${settings.machineId}`);
530
588
  return { credentials, machineId: settings.machineId };
531
589
  }
532
- async function ensureSigningCredentials(credentials) {
533
- if (credentials.signing) {
534
- return credentials;
535
- }
536
- try {
537
- const response = await axios.post(`${configuration.serverUrl}/v1/auth/refresh`, {}, {
538
- headers: buildAuthenticatedHeaders({
539
- credentials,
540
- method: "POST",
541
- url: `${configuration.serverUrl}/v1/auth/refresh`,
542
- body: {},
543
- headers: {
544
- "Content-Type": "application/json"
545
- },
546
- signRequest: false
547
- })
548
- });
549
- if (!response.data?.success || !response.data?.token || !response.data?.signing) {
550
- logger.debug("[AUTH] Signing bootstrap returned incomplete payload");
551
- return credentials;
552
- }
553
- const upgradedCredentials = {
554
- ...credentials,
555
- token: response.data.token,
556
- signing: response.data.signing
557
- };
558
- if (upgradedCredentials.encryption.type === "legacy") {
559
- await writeCredentialsLegacy({
560
- secret: upgradedCredentials.encryption.secret,
561
- token: upgradedCredentials.token,
562
- signing: upgradedCredentials.signing
563
- });
564
- } else {
565
- await writeCredentialsDataKey({
566
- publicKey: upgradedCredentials.encryption.publicKey,
567
- machineKey: upgradedCredentials.encryption.machineKey,
568
- token: upgradedCredentials.token,
569
- signing: upgradedCredentials.signing
570
- });
571
- }
572
- logger.debug("[AUTH] Signing credentials bootstrapped successfully");
573
- return upgradedCredentials;
574
- } catch (error) {
575
- logger.debug("[AUTH] Failed to bootstrap signing credentials", error);
576
- return credentials;
577
- }
578
- }
579
590
 
580
591
  let caffeinateProcess = null;
581
592
  function startCaffeinate() {
@@ -958,6 +969,32 @@ async function checkIfDaemonRunningAndCleanupStaleState() {
958
969
  return false;
959
970
  }
960
971
  }
972
+ async function isDaemonControlServerResponsive(timeoutMs = 1e3) {
973
+ const state = await readDaemonState();
974
+ if (!state?.httpPort) {
975
+ logger.debug("[DAEMON CONTROL] No daemon state or control port found for readiness check");
976
+ return false;
977
+ }
978
+ try {
979
+ process.kill(state.pid, 0);
980
+ } catch {
981
+ logger.debug("[DAEMON CONTROL] Daemon PID not running during readiness check, cleaning up state");
982
+ await cleanupDaemonState();
983
+ return false;
984
+ }
985
+ try {
986
+ const response = await fetch(`http://127.0.0.1:${state.httpPort}/list`, {
987
+ method: "POST",
988
+ headers: { "Content-Type": "application/json" },
989
+ body: JSON.stringify({}),
990
+ signal: AbortSignal.timeout(timeoutMs)
991
+ });
992
+ return response.ok;
993
+ } catch (error) {
994
+ logger.debug("[DAEMON CONTROL] Daemon control server not ready yet", error);
995
+ return false;
996
+ }
997
+ }
961
998
  async function isDaemonRunningCurrentlyInstalledHappyVersion() {
962
999
  logger.debug("[DAEMON CONTROL] Checking if daemon is running same version");
963
1000
  const runningDaemon = await checkIfDaemonRunningAndCleanupStaleState();
@@ -975,7 +1012,10 @@ async function isDaemonRunningCurrentlyInstalledHappyVersion() {
975
1012
  const packageJson = JSON.parse(readFileSync$1(packageJsonPath, "utf-8"));
976
1013
  const currentCliVersion = packageJson.version;
977
1014
  logger.debug(`[DAEMON CONTROL] Current CLI version: ${currentCliVersion}, Daemon started with version: ${state.startedWithCliVersion}`);
978
- return currentCliVersion === state.startedWithCliVersion;
1015
+ if (currentCliVersion !== state.startedWithCliVersion) {
1016
+ return false;
1017
+ }
1018
+ return await isDaemonControlServerResponsive();
979
1019
  } catch (error) {
980
1020
  logger.debug("[DAEMON CONTROL] Error checking daemon version", error);
981
1021
  return false;
@@ -1192,7 +1232,7 @@ ${typeLabels[type] || type}:`));
1192
1232
  }
1193
1233
  if (filter === "all" && allProcesses.length > 1) {
1194
1234
  console.log(chalk.bold("\n\u{1F4A1} Process Management"));
1195
- console.log(chalk.gray("To clean up runaway processes: happy doctor clean"));
1235
+ console.log(chalk.gray("To clean up runaway processes: hicloud doctor clean"));
1196
1236
  }
1197
1237
  } catch (error) {
1198
1238
  console.log(chalk.red("\u274C Error checking daemon status"));
@@ -1374,7 +1414,8 @@ function startDaemonControlServer({
1374
1414
  schema: {
1375
1415
  body: z.object({
1376
1416
  directory: z.string(),
1377
- sessionId: z.string().optional()
1417
+ sessionId: z.string().optional(),
1418
+ agent: z.enum(["claude", "codex", "gemini"]).optional()
1378
1419
  }),
1379
1420
  response: {
1380
1421
  200: z.object({
@@ -1395,9 +1436,9 @@ function startDaemonControlServer({
1395
1436
  }
1396
1437
  }
1397
1438
  }, async (request, reply) => {
1398
- const { directory, sessionId } = request.body;
1399
- logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}`);
1400
- const result = await spawnSession({ directory, sessionId });
1439
+ const { directory, sessionId, agent } = request.body;
1440
+ logger.debug(`[CONTROL SERVER] Spawn session request: dir=${directory}, sessionId=${sessionId || "new"}, agent=${agent || "claude"}`);
1441
+ const result = await spawnSession({ directory, sessionId, agent });
1401
1442
  switch (result.type) {
1402
1443
  case "success":
1403
1444
  if (!result.sessionId) {
@@ -2912,13 +2953,13 @@ async function handleAuthCommand(args) {
2912
2953
  }
2913
2954
  function showAuthHelp() {
2914
2955
  console.log(`
2915
- ${chalk.bold("happy-cloud auth")} - Authentication management
2956
+ ${chalk.bold("hicloud auth")} - Authentication management
2916
2957
 
2917
2958
  ${chalk.bold("Usage:")}
2918
- happy-cloud auth login [--force] Authenticate with Happy
2919
- happy-cloud auth logout [--yes] Remove authentication and machine data
2920
- happy-cloud auth status Show authentication status
2921
- happy-cloud auth help Show this help message
2959
+ hicloud auth login [--force] Authenticate with Happy
2960
+ hicloud auth logout [--yes] Remove authentication and machine data
2961
+ hicloud auth status Show authentication status
2962
+ hicloud auth help Show this help message
2922
2963
 
2923
2964
  ${chalk.bold("Options:")}
2924
2965
  --force Clear credentials, machine ID, and stop daemon before re-auth
@@ -2958,7 +2999,7 @@ async function handleAuthLogin(args) {
2958
2999
  console.log(chalk.green("\u2713 Already authenticated"));
2959
3000
  console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
2960
3001
  console.log(chalk.gray(` Host: ${os$1.hostname()}`));
2961
- console.log(chalk.gray(` Use 'happy-cloud auth login --force' to re-authenticate`));
3002
+ console.log(chalk.gray(` Use 'hicloud auth login --force' to re-authenticate`));
2962
3003
  return;
2963
3004
  } else if (existingCreds && !settings?.machineId) {
2964
3005
  console.log(chalk.yellow("\u26A0\uFE0F Credentials exist but machine ID is missing"));
@@ -2989,7 +3030,7 @@ async function handleAuthLogout(args = []) {
2989
3030
  let confirmed = skipConfirm;
2990
3031
  if (!confirmed) {
2991
3032
  if (isNonInteractive) {
2992
- throw new Error('Non-interactive terminal detected. Use "happy-cloud auth logout --yes" to confirm.');
3033
+ throw new Error('Non-interactive terminal detected. Use "hicloud auth logout --yes" to confirm.');
2993
3034
  }
2994
3035
  const rl = createInterface({
2995
3036
  input: process.stdin,
@@ -3012,7 +3053,7 @@ async function handleAuthLogout(args = []) {
3012
3053
  rmSync(happyDir, { recursive: true, force: true });
3013
3054
  }
3014
3055
  console.log(chalk.green("\u2713 Successfully logged out"));
3015
- console.log(chalk.gray(' Run "happy-cloud auth login" to authenticate again'));
3056
+ console.log(chalk.gray(' Run "hicloud auth login" to authenticate again'));
3016
3057
  } catch (error) {
3017
3058
  throw new Error(`Failed to logout: ${error instanceof Error ? error.message : "Unknown error"}`);
3018
3059
  }
@@ -3026,20 +3067,20 @@ async function handleAuthStatus() {
3026
3067
  console.log(chalk.bold("\nAuthentication Status\n"));
3027
3068
  if (!credentials) {
3028
3069
  console.log(chalk.red("\u2717 Not authenticated"));
3029
- console.log(chalk.gray(' Run "happy-cloud auth login" to authenticate'));
3070
+ console.log(chalk.gray(' Run "hicloud auth login" to authenticate'));
3030
3071
  return;
3031
3072
  }
3032
3073
  console.log(chalk.green("\u2713 Authenticated"));
3033
3074
  const tokenPreview = credentials.token.substring(0, 30) + "...";
3034
3075
  console.log(chalk.gray(` Token: ${tokenPreview}`));
3035
- console.log(chalk.gray(` Request signing: ${credentials.signing ? "ready" : "legacy credentials (will auto-upgrade on use)"}`));
3076
+ console.log(chalk.gray(` Request signing: ${describeSigningStatus(credentials)}`));
3036
3077
  if (settings?.machineId) {
3037
3078
  console.log(chalk.green("\u2713 Machine registered"));
3038
3079
  console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
3039
3080
  console.log(chalk.gray(` Host: ${os$1.hostname()}`));
3040
3081
  } else {
3041
3082
  console.log(chalk.yellow("\u26A0\uFE0F Machine not registered"));
3042
- console.log(chalk.gray(' Run "happy-cloud auth login --force" to fix this'));
3083
+ console.log(chalk.gray(' Run "hicloud auth login --force" to fix this'));
3043
3084
  }
3044
3085
  console.log(chalk.gray(`
3045
3086
  Data directory: ${configuration.happyCloudHomeDir}`));
@@ -3054,6 +3095,12 @@ async function handleAuthStatus() {
3054
3095
  console.log(chalk.gray("\u2717 Daemon not running"));
3055
3096
  }
3056
3097
  }
3098
+ function describeSigningStatus(credentials) {
3099
+ if (credentials.signing) {
3100
+ return "ready";
3101
+ }
3102
+ return "not initialized (server write requests may still fail until signing bootstrap succeeds)";
3103
+ }
3057
3104
 
3058
3105
  const CLIENT_ID$2 = "app_EMoamEEZ73f0CkXaXp7hrann";
3059
3106
  const AUTH_BASE_URL = "https://auth.openai.com";
@@ -3570,14 +3617,14 @@ async function handleConnectCommand(args) {
3570
3617
  }
3571
3618
  function showConnectHelp() {
3572
3619
  console.log(`
3573
- ${chalk.bold("happy-cloud connect")} - Connect AI vendor API keys to Happy cloud
3620
+ ${chalk.bold("hicloud connect")} - Connect AI vendor API keys to Happy cloud
3574
3621
 
3575
3622
  ${chalk.bold("Usage:")}
3576
- happy-cloud connect codex Store your Codex API key in Happy cloud
3577
- happy-cloud connect claude Store your Anthropic API key in Happy cloud
3578
- happy-cloud connect gemini Store your Gemini API key in Happy cloud
3579
- happy-cloud connect status Show connection status for all vendors
3580
- happy-cloud connect help Show this help message
3623
+ hicloud connect codex Store your Codex API key in Happy cloud
3624
+ hicloud connect claude Store your Anthropic API key in Happy cloud
3625
+ hicloud connect gemini Store your Gemini API key in Happy cloud
3626
+ hicloud connect status Show connection status for all vendors
3627
+ hicloud connect help Show this help message
3581
3628
 
3582
3629
  ${chalk.bold("Description:")}
3583
3630
  The connect command allows you to securely store your AI vendor API keys
@@ -3585,13 +3632,13 @@ ${chalk.bold("Description:")}
3585
3632
  without exposing your API keys locally.
3586
3633
 
3587
3634
  ${chalk.bold("Examples:")}
3588
- happy-cloud connect codex
3589
- happy-cloud connect claude
3590
- happy-cloud connect gemini
3591
- happy-cloud connect status
3635
+ hicloud connect codex
3636
+ hicloud connect claude
3637
+ hicloud connect gemini
3638
+ hicloud connect status
3592
3639
 
3593
3640
  ${chalk.bold("Notes:")}
3594
- \u2022 You must be authenticated with Happy first (run 'happy-cloud auth login')
3641
+ \u2022 You must be authenticated with Happy first (run 'hicloud auth login')
3595
3642
  \u2022 API keys are encrypted and stored securely in Happy cloud
3596
3643
  \u2022 You can manage your stored keys at https://happycloudcode.imou.com
3597
3644
  `);
@@ -3603,7 +3650,7 @@ async function handleConnectVendor(vendor, displayName) {
3603
3650
  const credentials = await readCredentials();
3604
3651
  if (!credentials) {
3605
3652
  console.log(chalk.yellow("\u26A0\uFE0F Not authenticated with Happy"));
3606
- console.log(chalk.gray(' Please run "happy-cloud auth login" first'));
3653
+ console.log(chalk.gray(' Please run "hicloud auth login" first'));
3607
3654
  process.exit(1);
3608
3655
  }
3609
3656
  const api = await ApiClient.create(credentials);
@@ -3635,7 +3682,7 @@ async function handleConnectStatus() {
3635
3682
  const credentials = await readCredentials();
3636
3683
  if (!credentials) {
3637
3684
  console.log(chalk.yellow("\u26A0\uFE0F Not authenticated with Happy"));
3638
- console.log(chalk.gray(' Please run "happy-cloud auth login" first'));
3685
+ console.log(chalk.gray(' Please run "hicloud auth login" first'));
3639
3686
  process.exit(1);
3640
3687
  }
3641
3688
  const api = await ApiClient.create(credentials);
@@ -3670,8 +3717,8 @@ async function handleConnectStatus() {
3670
3717
  }
3671
3718
  }
3672
3719
  console.log("");
3673
- console.log(chalk.gray("To connect a vendor, run: happy-cloud connect <vendor>"));
3674
- console.log(chalk.gray("Example: happy-cloud connect gemini"));
3720
+ console.log(chalk.gray("To connect a vendor, run: hicloud connect <vendor>"));
3721
+ console.log(chalk.gray("Example: hicloud connect gemini"));
3675
3722
  console.log("");
3676
3723
  }
3677
3724
  function updateLocalGeminiCredentials(tokens) {
@@ -3696,19 +3743,17 @@ function updateLocalGeminiCredentials(tokens) {
3696
3743
  }
3697
3744
  }
3698
3745
 
3699
- function getProjectPath(workingDirectory) {
3700
- let resolved = resolve$1(workingDirectory);
3701
- if (process.platform === "win32" && isAbsolute(resolved)) {
3702
- resolved = resolved.replace(/^[A-Z]:/i, "");
3703
- }
3704
- const projectId = resolved.replace(/[\\\/\.: _]/g, "-");
3705
- const claudeConfigDir = process.env.CLAUDE_CONFIG_DIR || join(homedir$1(), ".claude");
3746
+ function getProjectPath(workingDirectory, claudeConfigDirOverride) {
3747
+ const projectId = resolve$1(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
3748
+ const claudeConfigDirRaw = process.env.CLAUDE_CONFIG_DIR ?? "";
3749
+ const claudeConfigDirTrimmed = claudeConfigDirRaw.trim();
3750
+ const claudeConfigDir = claudeConfigDirTrimmed ? claudeConfigDirTrimmed : join(homedir$1(), ".claude");
3706
3751
  return join(claudeConfigDir, "projects", projectId);
3707
3752
  }
3708
3753
 
3709
- function claudeCheckSession(sessionId, path) {
3754
+ function claudeCheckSession(sessionId, path, transcriptPath) {
3710
3755
  const projectDir = getProjectPath(path);
3711
- const sessionFile = join(projectDir, `${sessionId}.jsonl`);
3756
+ const sessionFile = transcriptPath ?? join(projectDir, `${sessionId}.jsonl`);
3712
3757
  const sessionExists = existsSync(sessionFile);
3713
3758
  if (!sessionExists) {
3714
3759
  logger.debug(`[claudeCheckSession] Path ${sessionFile} does not exist`);
@@ -4056,6 +4101,77 @@ class AgentRegistry {
4056
4101
  }
4057
4102
  const agentRegistry = new AgentRegistry();
4058
4103
 
4104
+ const PREFERRED_MESSAGE_FIELDS = ["stderr", "error", "message", "detail", "stdout", "text", "reason"];
4105
+ function safeSerializeDisplayValue(value) {
4106
+ const seen = /* @__PURE__ */ new WeakSet();
4107
+ try {
4108
+ const serialized = JSON.stringify(value, (_key, currentValue) => {
4109
+ if (typeof currentValue === "bigint") {
4110
+ return currentValue.toString();
4111
+ }
4112
+ if (currentValue instanceof Error) {
4113
+ return {
4114
+ name: currentValue.name,
4115
+ message: currentValue.message,
4116
+ stack: currentValue.stack
4117
+ };
4118
+ }
4119
+ if (typeof currentValue === "object" && currentValue !== null) {
4120
+ if (seen.has(currentValue)) {
4121
+ return "[Circular]";
4122
+ }
4123
+ seen.add(currentValue);
4124
+ }
4125
+ return currentValue;
4126
+ });
4127
+ return serialized ?? String(value);
4128
+ } catch {
4129
+ return String(value);
4130
+ }
4131
+ }
4132
+ function formatDisplayMessage(value, seen = /* @__PURE__ */ new WeakSet()) {
4133
+ if (typeof value === "string") {
4134
+ return value;
4135
+ }
4136
+ if (value instanceof Error) {
4137
+ return value.message || String(value);
4138
+ }
4139
+ if (value === null || value === void 0) {
4140
+ return "";
4141
+ }
4142
+ if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) {
4143
+ return value.toString("utf8");
4144
+ }
4145
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
4146
+ return String(value);
4147
+ }
4148
+ if (typeof value === "object") {
4149
+ if (seen.has(value)) {
4150
+ return "[Circular]";
4151
+ }
4152
+ seen.add(value);
4153
+ const record = value;
4154
+ for (const field of PREFERRED_MESSAGE_FIELDS) {
4155
+ if (!(field in record)) {
4156
+ continue;
4157
+ }
4158
+ const formattedField = formatDisplayMessage(record[field], seen).trim();
4159
+ if (formattedField.length > 0) {
4160
+ return formattedField;
4161
+ }
4162
+ }
4163
+ return safeSerializeDisplayValue(value);
4164
+ }
4165
+ return String(value);
4166
+ }
4167
+ function truncateDisplayMessage(value, maxLength) {
4168
+ const formatted = formatDisplayMessage(value);
4169
+ if (formatted.length <= maxLength) {
4170
+ return formatted;
4171
+ }
4172
+ return `${formatted.substring(0, maxLength)}...`;
4173
+ }
4174
+
4059
4175
  const DEFAULT_TIMEOUTS = {
4060
4176
  /** Default initialization timeout: 60 seconds */
4061
4177
  init: 6e4,
@@ -4350,7 +4466,7 @@ class CodexTransport extends DefaultTransport {
4350
4466
  return 800;
4351
4467
  }
4352
4468
  }
4353
- const codexTransport = new CodexTransport();
4469
+ new CodexTransport();
4354
4470
 
4355
4471
  class ClaudeTransport extends DefaultTransport {
4356
4472
  constructor() {
@@ -4684,6 +4800,70 @@ const RETRY_CONFIG = {
4684
4800
  /** Maximum delay between retries in ms */
4685
4801
  maxDelayMs: 5e3
4686
4802
  };
4803
+ function getSessionUpdates(params) {
4804
+ const notification = params;
4805
+ const updates = Array.isArray(notification.updates) ? notification.updates.filter((update) => Boolean(update && typeof update === "object")) : [];
4806
+ if (updates.length > 0) {
4807
+ return updates;
4808
+ }
4809
+ if (notification.update && typeof notification.update === "object") {
4810
+ return [notification.update];
4811
+ }
4812
+ return [];
4813
+ }
4814
+ function asNonNegativeFiniteNumber(value) {
4815
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
4816
+ }
4817
+ function extractUsageTokens(record) {
4818
+ const used = asNonNegativeFiniteNumber(record.used);
4819
+ const size = asNonNegativeFiniteNumber(record.size);
4820
+ if (used != null || size != null) {
4821
+ const tokens2 = {
4822
+ total: used ?? 0
4823
+ };
4824
+ if (used != null) tokens2.used = used;
4825
+ if (size != null) tokens2.size = size;
4826
+ return tokens2;
4827
+ }
4828
+ const input = asNonNegativeFiniteNumber(record.input_tokens) ?? asNonNegativeFiniteNumber(record.inputTokens) ?? asNonNegativeFiniteNumber(record.prompt_tokens) ?? asNonNegativeFiniteNumber(record.promptTokens);
4829
+ const output = asNonNegativeFiniteNumber(record.output_tokens) ?? asNonNegativeFiniteNumber(record.outputTokens) ?? asNonNegativeFiniteNumber(record.completion_tokens) ?? asNonNegativeFiniteNumber(record.completionTokens);
4830
+ const cacheRead = asNonNegativeFiniteNumber(record.cache_read_input_tokens) ?? asNonNegativeFiniteNumber(record.cacheReadInputTokens) ?? asNonNegativeFiniteNumber(record.cache_read_tokens) ?? asNonNegativeFiniteNumber(record.cacheReadTokens) ?? asNonNegativeFiniteNumber(record.cached_read_tokens) ?? asNonNegativeFiniteNumber(record.cachedReadTokens);
4831
+ const cacheCreation = asNonNegativeFiniteNumber(record.cache_creation_input_tokens) ?? asNonNegativeFiniteNumber(record.cacheCreationInputTokens) ?? asNonNegativeFiniteNumber(record.cache_creation_tokens) ?? asNonNegativeFiniteNumber(record.cacheCreationTokens) ?? asNonNegativeFiniteNumber(record.cached_write_tokens) ?? asNonNegativeFiniteNumber(record.cachedWriteTokens);
4832
+ const thought = asNonNegativeFiniteNumber(record.thought_tokens) ?? asNonNegativeFiniteNumber(record.thoughtTokens);
4833
+ const totalFromPayload = asNonNegativeFiniteNumber(record.total_tokens) ?? asNonNegativeFiniteNumber(record.totalTokens);
4834
+ const anyPresent = totalFromPayload != null || input != null || output != null || cacheRead != null || cacheCreation != null || thought != null;
4835
+ if (!anyPresent) {
4836
+ return null;
4837
+ }
4838
+ const total = totalFromPayload ?? (input ?? 0) + (output ?? 0) + (cacheRead ?? 0) + (cacheCreation ?? 0) + (thought ?? 0);
4839
+ const tokens = { total };
4840
+ if (input != null) tokens.input = input;
4841
+ if (output != null) tokens.output = output;
4842
+ if (cacheRead != null) tokens.cache_read = cacheRead;
4843
+ if (cacheCreation != null) tokens.cache_creation = cacheCreation;
4844
+ if (thought != null) tokens.thought = thought;
4845
+ return tokens;
4846
+ }
4847
+ function isApprovalOption(option) {
4848
+ if (option.optionId === "proceed_once" || option.optionId === "proceed_always" || option.optionId === "cancel") {
4849
+ return true;
4850
+ }
4851
+ const searchable = `${option.name ?? ""} ${option.label ?? ""}`.toLowerCase();
4852
+ return searchable.includes("once") || searchable.includes("always") || searchable.includes("cancel");
4853
+ }
4854
+ function isSelectionPermissionRequest(params) {
4855
+ if (Array.isArray(params.codex_command) && params.codex_command.length > 0) {
4856
+ return false;
4857
+ }
4858
+ if (params.requestedSchema?.properties?.optionId) {
4859
+ return true;
4860
+ }
4861
+ const options = Array.isArray(params.options) ? params.options : [];
4862
+ if (options.length === 0) {
4863
+ return false;
4864
+ }
4865
+ return !options.every((option) => isApprovalOption(option));
4866
+ }
4687
4867
  function nodeToWebStreams(stdin, stdout) {
4688
4868
  const writable = new WritableStream({
4689
4869
  write(chunk) {
@@ -4747,7 +4927,7 @@ async function withRetry(operation, options) {
4747
4927
  try {
4748
4928
  return await operation();
4749
4929
  } catch (error) {
4750
- lastError = error instanceof Error ? error : new Error(String(error));
4930
+ lastError = normalizeAcpError(error);
4751
4931
  if (attempt < options.maxAttempts) {
4752
4932
  const delayMs = Math.min(
4753
4933
  options.baseDelayMs * Math.pow(2, attempt - 1),
@@ -4761,6 +4941,49 @@ async function withRetry(operation, options) {
4761
4941
  }
4762
4942
  throw lastError;
4763
4943
  }
4944
+ function formatAcpErrorMessage(error) {
4945
+ if (error instanceof Error && error.message && error.message !== "[object Object]") {
4946
+ return error.message;
4947
+ }
4948
+ if (typeof error === "object" && error !== null) {
4949
+ const record = error;
4950
+ const message = formatDisplayMessage(error).trim();
4951
+ const code = record.code;
4952
+ const status = record.status;
4953
+ const prefix = [
4954
+ code !== void 0 && code !== null ? `[code=${String(code)}]` : "",
4955
+ status !== void 0 && status !== null ? `[status=${String(status)}]` : ""
4956
+ ].filter(Boolean).join(" ");
4957
+ if (message.length > 0) {
4958
+ return prefix ? `${prefix} ${message}` : message;
4959
+ }
4960
+ }
4961
+ const fallback = formatDisplayMessage(error).trim();
4962
+ return fallback || "Unknown ACP error";
4963
+ }
4964
+ function normalizeAcpError(error) {
4965
+ if (error instanceof Error && error.message && error.message !== "[object Object]") {
4966
+ return error;
4967
+ }
4968
+ const normalized = new Error(formatAcpErrorMessage(error));
4969
+ normalized.name = error instanceof Error ? error.name : "Error";
4970
+ if (error && typeof error === "object") {
4971
+ const { message: _message, ...rest } = error;
4972
+ Object.assign(normalized, rest);
4973
+ }
4974
+ return normalized;
4975
+ }
4976
+ function enrichAcpError(error, stderrExcerpt) {
4977
+ const normalized = normalizeAcpError(error);
4978
+ if (!stderrExcerpt.trim()) {
4979
+ return normalized;
4980
+ }
4981
+ const existingStderr = normalized.stderr;
4982
+ if (typeof existingStderr !== "string" || existingStderr.trim().length === 0) {
4983
+ Object.assign(normalized, { stderr: stderrExcerpt });
4984
+ }
4985
+ return normalized;
4986
+ }
4764
4987
  class AcpBackend {
4765
4988
  constructor(options) {
4766
4989
  this.options = options;
@@ -4788,6 +5011,21 @@ class AcpBackend {
4788
5011
  idleTimeout = null;
4789
5012
  /** Transport handler for agent-specific behavior */
4790
5013
  transport;
5014
+ /** Keep a short rolling stderr buffer so startup failures can surface the real cause. */
5015
+ recentStderrLines = [];
5016
+ recordRecentStderr(text) {
5017
+ const normalized = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
5018
+ if (normalized.length === 0) {
5019
+ return;
5020
+ }
5021
+ this.recentStderrLines.push(...normalized);
5022
+ if (this.recentStderrLines.length > 12) {
5023
+ this.recentStderrLines = this.recentStderrLines.slice(-12);
5024
+ }
5025
+ }
5026
+ getRecentStderrExcerpt() {
5027
+ return this.recentStderrLines.slice(-6).join("\n");
5028
+ }
4791
5029
  onMessage(handler) {
4792
5030
  this.listeners.push(handler);
4793
5031
  }
@@ -4815,6 +5053,7 @@ class AcpBackend {
4815
5053
  this.emit({ type: "status", status: "starting" });
4816
5054
  try {
4817
5055
  logger.debug(`[AcpBackend] Starting session: ${sessionId}`);
5056
+ this.recentStderrLines = [];
4818
5057
  const args = this.options.args || [];
4819
5058
  if (process.platform === "win32") {
4820
5059
  const fullCommand = [this.options.command, ...args].join(" ");
@@ -4841,6 +5080,7 @@ class AcpBackend {
4841
5080
  this.process.stderr.on("data", (data) => {
4842
5081
  const text = data.toString();
4843
5082
  if (!text.trim()) return;
5083
+ this.recordRecentStderr(text);
4844
5084
  const hasActiveInvestigation = this.transport.isInvestigationTool ? Array.from(this.activeToolCalls).some((id) => this.transport.isInvestigationTool(id)) : false;
4845
5085
  const context = {
4846
5086
  activeToolCalls: this.activeToolCalls,
@@ -4951,6 +5191,7 @@ class AcpBackend {
4951
5191
  }
4952
5192
  this.toolCallCountSincePrompt++;
4953
5193
  const options = extendedParams.options || [];
5194
+ const isSelectionRequest = isSelectionPermissionRequest(extendedParams);
4954
5195
  logger.debug(`[AcpBackend] Permission request: tool=${toolName}, toolCallId=${toolCallId}, input=`, JSON.stringify(input));
4955
5196
  logger.debug(`[AcpBackend] Permission request params structure:`, JSON.stringify({
4956
5197
  hasToolCall: !!toolCall,
@@ -4959,6 +5200,42 @@ class AcpBackend {
4959
5200
  paramsKind: extendedParams.kind,
4960
5201
  paramsKeys: Object.keys(params)
4961
5202
  }, null, 2));
5203
+ if (isSelectionRequest) {
5204
+ const selectionOptions = options.reduce((acc, option) => {
5205
+ if (!option.optionId) {
5206
+ return acc;
5207
+ }
5208
+ const displayOption = option;
5209
+ acc.push({
5210
+ optionId: option.optionId,
5211
+ label: displayOption.label || option.name || option.optionId,
5212
+ description: displayOption.description || option.name || option.optionId
5213
+ });
5214
+ return acc;
5215
+ }, []);
5216
+ if (selectionOptions.length === 0) {
5217
+ logger.debug("[AcpBackend] Selection request has no valid options, cancelling");
5218
+ return { outcome: { outcome: "selected", optionId: "cancel" } };
5219
+ }
5220
+ if (!this.options.selectionHandler) {
5221
+ logger.debug("[AcpBackend] No selection handler configured, cancelling selection request");
5222
+ return { outcome: { outcome: "selected", optionId: "cancel" } };
5223
+ }
5224
+ try {
5225
+ const selectionMessage = typeof extendedParams.message === "string" && extendedParams.message.trim().length > 0 ? extendedParams.message : formatDisplayMessage(input).trim() || toolName;
5226
+ const requestId = extendedParams.codex_event_id || extendedParams.codex_elicitation || toolCallId;
5227
+ const response = await this.options.selectionHandler.handleSelection({
5228
+ id: requestId,
5229
+ message: selectionMessage,
5230
+ options: selectionOptions,
5231
+ defaultOptionId: extendedParams.requestedSchema?.properties?.optionId?.default
5232
+ });
5233
+ return { outcome: { outcome: "selected", optionId: response.optionId } };
5234
+ } catch (error) {
5235
+ logger.debug("[AcpBackend] Error in selection handler:", error);
5236
+ return { outcome: { outcome: "selected", optionId: "cancel" } };
5237
+ }
5238
+ }
4962
5239
  this.emit({
4963
5240
  type: "permission-request",
4964
5241
  id: permissionId,
@@ -5132,18 +5409,19 @@ class AcpBackend {
5132
5409
  if (initialPrompt) {
5133
5410
  this.sendPrompt(sessionId, initialPrompt).catch((error) => {
5134
5411
  logger.debug("[AcpBackend] Error sending initial prompt:", error);
5135
- this.emit({ type: "status", status: "error", detail: String(error) });
5412
+ this.emit({ type: "status", status: "error", detail: formatAcpErrorMessage(error) });
5136
5413
  });
5137
5414
  }
5138
5415
  return { sessionId };
5139
5416
  } catch (error) {
5140
- logger.debug("[AcpBackend] Error starting session:", error);
5417
+ const enrichedError = enrichAcpError(error, this.getRecentStderrExcerpt());
5418
+ logger.debug("[AcpBackend] Error starting session:", enrichedError);
5141
5419
  this.emit({
5142
5420
  type: "status",
5143
5421
  status: "error",
5144
- detail: error instanceof Error ? error.message : String(error)
5422
+ detail: formatAcpErrorMessage(enrichedError)
5145
5423
  });
5146
- throw error;
5424
+ throw enrichedError;
5147
5425
  }
5148
5426
  }
5149
5427
  /**
@@ -5174,51 +5452,73 @@ class AcpBackend {
5174
5452
  }
5175
5453
  };
5176
5454
  }
5455
+ emitUsageTelemetry(payload, source) {
5456
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
5457
+ return false;
5458
+ }
5459
+ const tokens = extractUsageTokens(payload);
5460
+ if (!tokens) {
5461
+ return false;
5462
+ }
5463
+ this.emit({
5464
+ type: "token-count",
5465
+ key: source,
5466
+ tokens,
5467
+ source
5468
+ });
5469
+ return true;
5470
+ }
5177
5471
  handleSessionUpdate(params) {
5178
- const notification = params;
5179
- const update = notification.update;
5180
- if (!update) {
5472
+ const updates = getSessionUpdates(params);
5473
+ if (updates.length === 0) {
5181
5474
  logger.debug("[AcpBackend] Received session update without update field:", params);
5182
5475
  return;
5183
5476
  }
5184
- const sessionUpdateType = update.sessionUpdate;
5185
- if (sessionUpdateType !== "agent_message_chunk") {
5186
- logger.debug(`[AcpBackend] Received session update: ${sessionUpdateType}`, JSON.stringify({
5187
- sessionUpdate: sessionUpdateType,
5188
- toolCallId: update.toolCallId,
5189
- status: update.status,
5190
- kind: update.kind,
5191
- hasContent: !!update.content,
5192
- hasLocations: !!update.locations
5193
- }, null, 2));
5194
- }
5195
- const ctx = this.createHandlerContext();
5196
- if (sessionUpdateType === "agent_message_chunk") {
5197
- handleAgentMessageChunk(update, ctx);
5198
- return;
5199
- }
5200
- if (sessionUpdateType === "tool_call_update") {
5201
- const result = handleToolCallUpdate(update, ctx);
5202
- if (result.toolCallCountSincePrompt !== void 0) {
5203
- this.toolCallCountSincePrompt = result.toolCallCountSincePrompt;
5477
+ for (const update of updates) {
5478
+ const sessionUpdateType = update.sessionUpdate;
5479
+ if (sessionUpdateType !== "agent_message_chunk") {
5480
+ logger.debug(`[AcpBackend] Received session update: ${sessionUpdateType}`, JSON.stringify({
5481
+ sessionUpdate: sessionUpdateType,
5482
+ toolCallId: update.toolCallId,
5483
+ status: update.status,
5484
+ kind: update.kind,
5485
+ hasContent: !!update.content,
5486
+ hasLocations: !!update.locations
5487
+ }, null, 2));
5488
+ }
5489
+ const ctx = this.createHandlerContext();
5490
+ if (sessionUpdateType === "agent_message_chunk") {
5491
+ handleAgentMessageChunk(update, ctx);
5492
+ continue;
5493
+ }
5494
+ if (sessionUpdateType === "tool_call_update") {
5495
+ const result = handleToolCallUpdate(update, ctx);
5496
+ if (result.toolCallCountSincePrompt !== void 0) {
5497
+ this.toolCallCountSincePrompt = result.toolCallCountSincePrompt;
5498
+ }
5499
+ continue;
5500
+ }
5501
+ if (sessionUpdateType === "agent_thought_chunk") {
5502
+ handleAgentThoughtChunk(update, ctx);
5503
+ continue;
5504
+ }
5505
+ if (sessionUpdateType === "tool_call") {
5506
+ handleToolCall(update, ctx);
5507
+ continue;
5508
+ }
5509
+ if (sessionUpdateType === "usage_update") {
5510
+ this.emitUsageTelemetry(update, "acp-usage-update");
5511
+ continue;
5512
+ }
5513
+ const handledLegacy = handleLegacyMessageChunk(update, ctx).handled;
5514
+ const handledPlan = handlePlanUpdate(update, ctx).handled;
5515
+ const handledThinking = handleThinkingUpdate(update, ctx).handled;
5516
+ const handledUsage = this.emitUsageTelemetry(update.usage, "acp-session-usage");
5517
+ const updateTypeStr = sessionUpdateType;
5518
+ const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call", "usage_update"];
5519
+ if (updateTypeStr && !handledTypes.includes(updateTypeStr) && !handledLegacy && !handledPlan && !handledThinking && !handledUsage) {
5520
+ logger.debug(`[AcpBackend] Unhandled session update type: ${updateTypeStr}`, JSON.stringify(update, null, 2));
5204
5521
  }
5205
- return;
5206
- }
5207
- if (sessionUpdateType === "agent_thought_chunk") {
5208
- handleAgentThoughtChunk(update, ctx);
5209
- return;
5210
- }
5211
- if (sessionUpdateType === "tool_call") {
5212
- handleToolCall(update, ctx);
5213
- return;
5214
- }
5215
- handleLegacyMessageChunk(update, ctx);
5216
- handlePlanUpdate(update, ctx);
5217
- handleThinkingUpdate(update, ctx);
5218
- const updateTypeStr = sessionUpdateType;
5219
- const handledTypes = ["agent_message_chunk", "tool_call_update", "agent_thought_chunk", "tool_call"];
5220
- if (updateTypeStr && !handledTypes.includes(updateTypeStr) && !update.messageChunk && !update.plan && !update.thinking) {
5221
- logger.debug(`[AcpBackend] Unhandled session update type: ${updateTypeStr}`, JSON.stringify(update, null, 2));
5222
5522
  }
5223
5523
  }
5224
5524
  // Promise resolver for waitForIdle - set when waiting for response to complete
@@ -5255,17 +5555,9 @@ class AcpBackend {
5255
5555
  if (error instanceof Error) {
5256
5556
  errorDetail = error.message;
5257
5557
  } else if (typeof error === "object" && error !== null) {
5258
- const errObj = error;
5259
- const fallbackMessage = (typeof errObj.message === "string" ? errObj.message : void 0) || String(error);
5260
- if (errObj.code !== void 0) {
5261
- errorDetail = JSON.stringify({ code: errObj.code, message: fallbackMessage });
5262
- } else if (typeof errObj.message === "string") {
5263
- errorDetail = errObj.message;
5264
- } else {
5265
- errorDetail = String(error);
5266
- }
5558
+ errorDetail = formatAcpErrorMessage(error);
5267
5559
  } else {
5268
- errorDetail = String(error);
5560
+ errorDetail = formatAcpErrorMessage(error);
5269
5561
  }
5270
5562
  this.emit({
5271
5563
  type: "status",
@@ -5616,59 +5908,213 @@ function registerGeminiAgent() {
5616
5908
  logger.debug("[Gemini] Registered with agent registry");
5617
5909
  }
5618
5910
 
5619
- function firstExistingPath(candidates) {
5620
- for (const candidate of candidates) {
5621
- try {
5622
- if (fs$1.existsSync(candidate)) {
5911
+ function readFirstEnv(...names) {
5912
+ for (const name of names) {
5913
+ const raw = process.env[name];
5914
+ if (typeof raw === "string" && raw.trim()) {
5915
+ return raw.trim();
5916
+ }
5917
+ }
5918
+ return "";
5919
+ }
5920
+ function normalizeCommandPath(command) {
5921
+ if (isAbsolute(command)) {
5922
+ return command;
5923
+ }
5924
+ const resolved = resolve$1(process.cwd(), command);
5925
+ return existsSync(resolved) ? resolved : command;
5926
+ }
5927
+ function resolveCommandOnPath(command) {
5928
+ const pathValue = typeof process.env.PATH === "string" ? process.env.PATH : "";
5929
+ if (!pathValue) {
5930
+ return null;
5931
+ }
5932
+ const extensions = process.platform === "win32" ? (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD").split(";").map((value) => value.trim().toLowerCase()).filter(Boolean) : [""];
5933
+ for (const dir of pathValue.split(delimiter)) {
5934
+ const trimmedDir = dir.trim();
5935
+ if (!trimmedDir) {
5936
+ continue;
5937
+ }
5938
+ const directCandidate = join(trimmedDir, command);
5939
+ if (existsSync(directCandidate)) {
5940
+ return directCandidate;
5941
+ }
5942
+ if (process.platform !== "win32") {
5943
+ continue;
5944
+ }
5945
+ const hasExtension = /\.[^\\/]+$/.test(command);
5946
+ if (hasExtension) {
5947
+ continue;
5948
+ }
5949
+ for (const extension of extensions) {
5950
+ const candidate = join(trimmedDir, `${command}${extension.toLowerCase()}`);
5951
+ if (existsSync(candidate)) {
5623
5952
  return candidate;
5624
5953
  }
5625
- } catch {
5626
5954
  }
5627
5955
  }
5628
5956
  return null;
5629
5957
  }
5630
- function resolveCodexExecutable() {
5631
- if (process.platform === "win32") {
5632
- const appData = process.env.APPDATA || path.join(os$1.homedir(), "AppData", "Roaming");
5633
- const npmGlobalBin = path.join(appData, "npm");
5634
- const resolved = firstExistingPath([
5635
- path.join(npmGlobalBin, "codex.cmd"),
5636
- path.join(npmGlobalBin, "codex.ps1"),
5637
- path.join(npmGlobalBin, "codex")
5638
- ]);
5639
- if (resolved) {
5640
- return resolved;
5641
- }
5958
+ function readCodexAcpNpxMode() {
5959
+ const raw = readFirstEnv("HAPPY_CODEX_ACP_NPX_MODE", "HAPPIER_CODEX_ACP_NPX_MODE").toLowerCase();
5960
+ if (raw === "auto" || raw === "never" || raw === "force") {
5961
+ return raw;
5642
5962
  }
5643
- return "codex";
5963
+ return "auto";
5964
+ }
5965
+ function isBinOnPath(baseName) {
5966
+ return resolveCommandOnPath(baseName) !== null;
5644
5967
  }
5645
- function shouldUseShellForCodex(executable) {
5646
- return process.platform === "win32" && /\.(cmd|bat|ps1)$/i.test(executable);
5968
+ function readCodexAcpConfigOverrides() {
5969
+ const raw = readFirstEnv("HAPPY_CODEX_ACP_CONFIG_OVERRIDES", "HAPPIER_CODEX_ACP_CONFIG_OVERRIDES");
5970
+ return raw.split("\n").map((line) => line.trim()).filter(Boolean);
5971
+ }
5972
+ function buildCodexAcpConfigArgs(options) {
5973
+ const args = [...options.baseArgs ?? []];
5974
+ const overrides = [...readCodexAcpConfigOverrides()];
5975
+ if (options.model) {
5976
+ overrides.push(`model=${JSON.stringify(options.model)}`);
5977
+ }
5978
+ if (options.approvalPolicy) {
5979
+ overrides.push(`approval_policy=${JSON.stringify(options.approvalPolicy)}`);
5980
+ }
5981
+ if (options.sandbox) {
5982
+ overrides.push(`sandbox_mode=${JSON.stringify(options.sandbox)}`);
5983
+ }
5984
+ for (const override of overrides) {
5985
+ args.push("-c", override);
5986
+ }
5987
+ return args;
5988
+ }
5989
+ function resolveNpxCommand() {
5990
+ return resolveCommandOnPath(process.platform === "win32" ? "npx.cmd" : "npx") ?? resolveCommandOnPath("npx") ?? (process.platform === "win32" ? "npx.cmd" : "npx");
5991
+ }
5992
+ function resolveCodexAcpSpawn(options = {}) {
5993
+ if (options.args) {
5994
+ const command = normalizeCommandPath(options.command || readFirstEnv("HAPPY_CODEX_ACP_BIN", "HAPPY_CODEX_ACP_COMMAND", "HAPPIER_CODEX_ACP_BIN") || "codex-acp");
5995
+ return {
5996
+ command,
5997
+ args: [...options.args]
5998
+ };
5999
+ }
6000
+ const directArgs = buildCodexAcpConfigArgs(options);
6001
+ if (options.command) {
6002
+ return {
6003
+ command: normalizeCommandPath(options.command),
6004
+ args: directArgs
6005
+ };
6006
+ }
6007
+ const envOverride = readFirstEnv("HAPPY_CODEX_ACP_BIN", "HAPPY_CODEX_ACP_COMMAND", "HAPPIER_CODEX_ACP_BIN");
6008
+ if (envOverride) {
6009
+ return {
6010
+ command: normalizeCommandPath(envOverride),
6011
+ args: directArgs
6012
+ };
6013
+ }
6014
+ const npxMode = readCodexAcpNpxMode();
6015
+ const codexAcpOnPath = resolveCommandOnPath(process.platform === "win32" ? "codex-acp.cmd" : "codex-acp") ?? resolveCommandOnPath("codex-acp");
6016
+ if (npxMode !== "force" && codexAcpOnPath) {
6017
+ return {
6018
+ command: codexAcpOnPath,
6019
+ args: directArgs
6020
+ };
6021
+ }
6022
+ if (npxMode === "never") {
6023
+ return {
6024
+ command: process.platform === "win32" ? "codex-acp.cmd" : "codex-acp",
6025
+ args: directArgs
6026
+ };
6027
+ }
6028
+ return {
6029
+ command: resolveNpxCommand(),
6030
+ args: ["--prefer-offline", "-y", "@zed-industries/codex-acp", ...directArgs]
6031
+ };
6032
+ }
6033
+ function validateCodexAcpSpawn(options = {}) {
6034
+ let spawn;
6035
+ try {
6036
+ spawn = resolveCodexAcpSpawn(options);
6037
+ } catch (error) {
6038
+ return {
6039
+ ok: false,
6040
+ errorMessage: error instanceof Error ? error.message : "Codex ACP is enabled, but the command could not be resolved."
6041
+ };
6042
+ }
6043
+ const normalizedCommand = spawn.command.trim();
6044
+ const commandLower = normalizedCommand.toLowerCase();
6045
+ const npxMode = readCodexAcpNpxMode();
6046
+ if (isAbsolute(normalizedCommand)) {
6047
+ if (!existsSync(normalizedCommand)) {
6048
+ return {
6049
+ ok: false,
6050
+ errorMessage: `Codex ACP is enabled, but the resolved command does not exist: ${normalizedCommand}`
6051
+ };
6052
+ }
6053
+ return { ok: true, spawn };
6054
+ }
6055
+ if (commandLower.endsWith("npx") || commandLower.endsWith("npx.cmd")) {
6056
+ if (isBinOnPath("npx") || isBinOnPath("npx.cmd")) {
6057
+ return { ok: true, spawn };
6058
+ }
6059
+ return {
6060
+ ok: false,
6061
+ errorMessage: "Codex ACP is enabled, but codex-acp is not installed and npx is not available. Install codex-acp, install Node.js/npm so npx is available, or set HAPPY_CODEX_ACP_BIN to a working codex-acp executable."
6062
+ };
6063
+ }
6064
+ if (commandLower === "codex-acp" || commandLower === "codex-acp.cmd") {
6065
+ if (isBinOnPath("codex-acp") || isBinOnPath("codex-acp.cmd")) {
6066
+ return { ok: true, spawn };
6067
+ }
6068
+ return {
6069
+ ok: false,
6070
+ errorMessage: npxMode === "never" ? "Codex ACP is enabled, but codex-acp is not installed and npx fallback is disabled. Install codex-acp, add it to PATH, or set HAPPY_CODEX_ACP_BIN to the executable." : "Codex ACP is enabled, but codex-acp could not be resolved on PATH. Install codex-acp, add it to PATH, or set HAPPY_CODEX_ACP_BIN to the executable."
6071
+ };
6072
+ }
6073
+ return { ok: true, spawn };
5647
6074
  }
5648
6075
 
5649
- function defaultCodexArgs() {
5650
- return ["mcp-server"];
6076
+ class CodexAcpTransport extends CodexTransport {
6077
+ constructor(initTimeoutMs) {
6078
+ super();
6079
+ this.initTimeoutMs = initTimeoutMs;
6080
+ }
6081
+ getInitTimeout() {
6082
+ return this.initTimeoutMs;
6083
+ }
6084
+ }
6085
+ function resolveCodexTransport(command) {
6086
+ if (/npx(?:\.cmd)?$/i.test(command)) {
6087
+ return new CodexAcpTransport(18e4);
6088
+ }
6089
+ return new CodexAcpTransport(6e4);
5651
6090
  }
5652
6091
  function createCodexBackend(options) {
5653
- const command = options.command ?? process.env.HAPPY_CODEX_ACP_COMMAND ?? resolveCodexExecutable();
5654
- const args = options.args ?? defaultCodexArgs();
6092
+ const spawn = resolveCodexAcpSpawn({
6093
+ command: options.command,
6094
+ args: options.args,
6095
+ baseArgs: options.baseArgs,
6096
+ model: options.model,
6097
+ sandbox: options.sandbox,
6098
+ approvalPolicy: options.approvalPolicy
6099
+ });
5655
6100
  const backendOptions = {
5656
6101
  agentName: "codex",
5657
6102
  cwd: options.cwd,
5658
- command,
5659
- args,
6103
+ command: spawn.command,
6104
+ args: spawn.args,
5660
6105
  env: {
5661
6106
  ...options.env,
5662
6107
  NODE_ENV: "production"
5663
6108
  },
5664
6109
  mcpServers: options.mcpServers,
5665
6110
  permissionHandler: options.permissionHandler,
5666
- transportHandler: codexTransport
6111
+ selectionHandler: options.selectionHandler,
6112
+ transportHandler: resolveCodexTransport(spawn.command)
5667
6113
  };
5668
6114
  return {
5669
6115
  backend: new AcpBackend(backendOptions),
5670
- command,
5671
- args
6116
+ command: spawn.command,
6117
+ args: spawn.args
5672
6118
  };
5673
6119
  }
5674
6120
  function registerCodexAgent() {
@@ -5854,17 +6300,26 @@ async function ensureUnifiedDaemonStarted() {
5854
6300
  env: process.env
5855
6301
  });
5856
6302
  daemonProcess.unref();
5857
- await new Promise((resolve) => setTimeout(resolve, 200));
6303
+ for (let i = 0; i < 100; i++) {
6304
+ if (await isDaemonRunningCurrentlyInstalledHappyVersion()) {
6305
+ return;
6306
+ }
6307
+ if (await isDaemonControlServerResponsive(500)) {
6308
+ return;
6309
+ }
6310
+ await new Promise((resolve) => setTimeout(resolve, 100));
6311
+ }
6312
+ throw new Error("Failed to start Happy background service.");
5858
6313
  }
5859
6314
  async function executeUnifiedProvider(opts) {
5860
6315
  const credentials = await ensureUnifiedRuntimePrerequisites(opts.credentials);
5861
6316
  if (opts.provider === "claude") {
5862
- const { runClaude } = await import('./runClaude-uNC5Eym4.mjs');
6317
+ const { runClaude } = await import('./runClaude-Cii3R2Fv.mjs');
5863
6318
  await runClaude(credentials, opts.claudeOptions ?? {});
5864
6319
  return;
5865
6320
  }
5866
6321
  if (opts.provider === "codex") {
5867
- const { runCodex } = await import('./runCodex-B-05E-YZ.mjs');
6322
+ const { runCodex } = await import('./runCodex-C--ZwAhl.mjs');
5868
6323
  await runCodex({
5869
6324
  credentials,
5870
6325
  startedBy: opts.startedBy,
@@ -5874,7 +6329,7 @@ async function executeUnifiedProvider(opts) {
5874
6329
  return;
5875
6330
  }
5876
6331
  if (opts.provider === "gemini") {
5877
- const { runGemini } = await import('./runGemini-_biXvQAH.mjs');
6332
+ const { runGemini } = await import('./runGemini-CQp7Nuzn.mjs');
5878
6333
  await runGemini({
5879
6334
  credentials,
5880
6335
  startedBy: opts.startedBy
@@ -5887,6 +6342,10 @@ async function executeUnifiedProvider(opts) {
5887
6342
  });
5888
6343
  }
5889
6344
 
6345
+ function shouldRunMainClaudeFlow(opts) {
6346
+ return !opts.showHelp && !opts.showVersion;
6347
+ }
6348
+
5890
6349
  (async () => {
5891
6350
  const args = process.argv.slice(2);
5892
6351
  const isRemoteMode = args.includes("--happy-starting-mode") && args.includes("remote");
@@ -5895,7 +6354,7 @@ async function executeUnifiedProvider(opts) {
5895
6354
  Object.defineProperty(process.stderr, "isTTY", { value: false });
5896
6355
  }
5897
6356
  if (!args.includes("--version")) {
5898
- logger.debug("Starting happy-cloud CLI with args: ", process.argv);
6357
+ logger.debug("Starting hicloud CLI with args: ", process.argv);
5899
6358
  }
5900
6359
  const subcommand = args[0];
5901
6360
  if (!args.includes("--version")) ;
@@ -5912,7 +6371,7 @@ async function executeUnifiedProvider(opts) {
5912
6371
  return;
5913
6372
  } else if (subcommand === "runtime") {
5914
6373
  if (args[1] === "providers") {
5915
- const { renderRuntimeProviders } = await import('./command-CnLtKtP-.mjs');
6374
+ const { renderRuntimeProviders } = await import('./command-nmK6O-ab.mjs');
5916
6375
  console.log(renderRuntimeProviders());
5917
6376
  return;
5918
6377
  }
@@ -5938,8 +6397,8 @@ async function executeUnifiedProvider(opts) {
5938
6397
  }
5939
6398
  return;
5940
6399
  }
5941
- console.log("Usage: happy-cloud runtime providers");
5942
- console.log(" happy-cloud runtime launch <claude|codex|gemini|cursor> [prompt]");
6400
+ console.log("Usage: hicloud runtime providers");
6401
+ console.log(" hicloud runtime launch <claude|codex|gemini|cursor> [prompt]");
5943
6402
  return;
5944
6403
  } else if (subcommand === "auth") {
5945
6404
  try {
@@ -6090,8 +6549,8 @@ async function executeUnifiedProvider(opts) {
6090
6549
  const projectId = args[3];
6091
6550
  try {
6092
6551
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
6093
- const { readCredentials: readCredentials2 } = await import('./persistence-BA_unuca.mjs');
6094
- const { ApiClient: ApiClient2 } = await import('./api-BGXYX0yH.mjs').then(function (n) { return n.n; });
6552
+ const { readCredentials: readCredentials2 } = await import('./persistence-Dkm7rm8k.mjs');
6553
+ const { ApiClient: ApiClient2 } = await import('./api-MYhAGPLn.mjs').then(function (n) { return n.q; });
6095
6554
  let userEmail = void 0;
6096
6555
  try {
6097
6556
  const credentials = await readCredentials2();
@@ -6137,7 +6596,7 @@ async function executeUnifiedProvider(opts) {
6137
6596
  console.log("No Google Cloud Project configured.");
6138
6597
  console.log("");
6139
6598
  console.log('If you see "Authentication required" error, you may need to set a project:');
6140
- console.log(" happy-cloud gemini project set <your-project-id>");
6599
+ console.log(" hicloud gemini project set <your-project-id>");
6141
6600
  console.log("");
6142
6601
  console.log("This is required for Google Workspace accounts.");
6143
6602
  console.log("Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca");
@@ -6149,7 +6608,7 @@ async function executeUnifiedProvider(opts) {
6149
6608
  }
6150
6609
  }
6151
6610
  if (geminiSubcommand === "project" && !args[2]) {
6152
- console.log("Usage: happy-cloud gemini project <command>");
6611
+ console.log("Usage: hicloud gemini project <command>");
6153
6612
  console.log("");
6154
6613
  console.log("Commands:");
6155
6614
  console.log(" set <project-id> Set Google Cloud Project ID");
@@ -6181,7 +6640,7 @@ async function executeUnifiedProvider(opts) {
6181
6640
  }
6182
6641
  return;
6183
6642
  } else if (subcommand === "logout") {
6184
- console.log(chalk.yellow('Note: "happy-cloud logout" is deprecated. Use "happy-cloud auth logout" instead.\n'));
6643
+ console.log(chalk.yellow('Note: "hicloud logout" is deprecated. Use "hicloud auth logout" instead.\n'));
6185
6644
  try {
6186
6645
  await handleAuthCommand(["logout"]);
6187
6646
  } catch (error) {
@@ -6240,7 +6699,7 @@ async function executeUnifiedProvider(opts) {
6240
6699
  child.unref();
6241
6700
  let started = false;
6242
6701
  for (let i = 0; i < 100; i++) {
6243
- if (await checkIfDaemonRunningAndCleanupStaleState()) {
6702
+ if (await checkIfDaemonRunningAndCleanupStaleState() && await isDaemonControlServerResponsive(500)) {
6244
6703
  started = true;
6245
6704
  break;
6246
6705
  }
@@ -6297,20 +6756,20 @@ async function executeUnifiedProvider(opts) {
6297
6756
  }
6298
6757
  } else {
6299
6758
  console.log(`
6300
- ${chalk.bold("happy-cloud daemon")} - Daemon management
6759
+ ${chalk.bold("hicloud daemon")} - Daemon management
6301
6760
 
6302
6761
  ${chalk.bold("Usage:")}
6303
- happy-cloud daemon start Start the daemon (detached)
6304
- happy-cloud daemon stop Stop the daemon (sessions stay alive)
6305
- happy-cloud daemon status Show daemon status
6306
- happy-cloud daemon list List active sessions
6762
+ hicloud daemon start Start the daemon (detached)
6763
+ hicloud daemon stop Stop the daemon (sessions stay alive)
6764
+ hicloud daemon status Show daemon status
6765
+ hicloud daemon list List active sessions
6307
6766
 
6308
6767
  If you want to kill all happy related processes run
6309
- ${chalk.cyan("happy-cloud doctor clean")}
6768
+ ${chalk.cyan("hicloud doctor clean")}
6310
6769
 
6311
6770
  ${chalk.bold("Note:")} The daemon runs in the background and manages Claude sessions.
6312
6771
 
6313
- ${chalk.bold("To clean up runaway processes:")} Use ${chalk.cyan("happy-cloud doctor clean")}
6772
+ ${chalk.bold("To clean up runaway processes:")} Use ${chalk.cyan("hicloud doctor clean")}
6314
6773
  `);
6315
6774
  }
6316
6775
  return;
@@ -6385,33 +6844,33 @@ ${chalk.bold("To clean up runaway processes:")} Use ${chalk.cyan("happy-cloud do
6385
6844
  ${chalk.bold(BRAND_CONFIG.name)} - AI \u7F16\u7A0B\u52A9\u624B
6386
6845
 
6387
6846
  ${chalk.bold("Usage:")}
6388
- happy-cloud [options] Start Claude with mobile control
6389
- happy-cloud auth Manage authentication
6390
- happy-cloud codex Start Codex mode
6391
- happy-cloud gemini Start Gemini mode (ACP)
6392
- happy-cloud cursor Start Cursor mode (experimental ACP)
6393
- happy-cloud connect Connect AI vendor API keys
6394
- happy-cloud notify Send push notification
6395
- happy-cloud daemon Manage background service that allows
6847
+ hicloud [options] Start Claude with mobile control
6848
+ hicloud auth Manage authentication
6849
+ hicloud codex Start Codex mode
6850
+ hicloud gemini Start Gemini mode (ACP)
6851
+ hicloud cursor Start Cursor mode (experimental ACP)
6852
+ hicloud connect Connect AI vendor API keys
6853
+ hicloud notify Send push notification
6854
+ hicloud daemon Manage background service that allows
6396
6855
  to spawn new sessions away from your computer
6397
- happy-cloud doctor System diagnostics & troubleshooting
6856
+ hicloud doctor System diagnostics & troubleshooting
6398
6857
 
6399
6858
  ${chalk.bold("Examples:")}
6400
- happy-cloud Start session
6401
- happy-cloud --yolo Start with bypassing permissions
6402
- happy-cloud sugar for --dangerously-skip-permissions
6403
- happy-cloud --chrome Enable Chrome browser access for this session
6404
- happy-cloud --no-chrome Disable Chrome even if default is on
6405
- happy-cloud --js-runtime bun Use bun instead of node to spawn Claude Code
6406
- happy-cloud --claude-env ANTHROPIC_BASE_URL=http://127.0.0.1:3456
6859
+ hicloud Start session
6860
+ hicloud --yolo Start with bypassing permissions
6861
+ hicloud sugar for --dangerously-skip-permissions
6862
+ hicloud --chrome Enable Chrome browser access for this session
6863
+ hicloud --no-chrome Disable Chrome even if default is on
6864
+ hicloud --js-runtime bun Use bun instead of node to spawn Claude Code
6865
+ hicloud --claude-env ANTHROPIC_BASE_URL=http://127.0.0.1:3456
6407
6866
  Use a custom API endpoint (e.g., claude-code-router)
6408
- happy-cloud auth login --force Authenticate
6409
- happy-cloud doctor Run diagnostics
6867
+ hicloud auth login --force Authenticate
6868
+ hicloud doctor Run diagnostics
6410
6869
 
6411
6870
  ${chalk.bold(`${BRAND_CONFIG.name} supports ALL Claude options!`)}
6412
- Use any claude flag with happy-cloud as you would with claude. Our favorite:
6871
+ Use any claude flag with hicloud as you would with claude. Our favorite:
6413
6872
 
6414
- happy-cloud --resume
6873
+ hicloud --resume
6415
6874
 
6416
6875
  ${chalk.gray("\u2500".repeat(60))}
6417
6876
  ${chalk.bold.cyan("Claude Code Options (from `claude --help`):")}
@@ -6426,8 +6885,9 @@ ${chalk.bold.cyan("Claude Code Options (from `claude --help`):")}
6426
6885
  }
6427
6886
  if (showVersion) {
6428
6887
  console.log(getVersionString());
6888
+ return;
6429
6889
  }
6430
- if (!showHelp && !showVersion) {
6890
+ if (shouldRunMainClaudeFlow({ showHelp, showVersion })) {
6431
6891
  printBanner();
6432
6892
  }
6433
6893
  try {
@@ -6463,31 +6923,31 @@ async function handleNotifyCommand(args) {
6463
6923
  }
6464
6924
  if (showHelp) {
6465
6925
  console.log(`
6466
- ${chalk.bold("happy-cloud notify")} - Send notification
6926
+ ${chalk.bold("hicloud notify")} - Send notification
6467
6927
 
6468
6928
  ${chalk.bold("Usage:")}
6469
- happy-cloud notify -p <message> [-t <title>] Send notification with custom message and optional title
6470
- happy-cloud notify -h, --help Show this help
6929
+ hicloud notify -p <message> [-t <title>] Send notification with custom message and optional title
6930
+ hicloud notify -h, --help Show this help
6471
6931
 
6472
6932
  ${chalk.bold("Options:")}
6473
6933
  -p <message> Notification message (required)
6474
6934
  -t <title> Notification title (optional, defaults to "Happy")
6475
6935
 
6476
6936
  ${chalk.bold("Examples:")}
6477
- happy-cloud notify -p "Deployment complete!"
6478
- happy-cloud notify -p "System update complete" -t "Server Status"
6479
- happy-cloud notify -t "Alert" -p "Database connection restored"
6937
+ hicloud notify -p "Deployment complete!"
6938
+ hicloud notify -p "System update complete" -t "Server Status"
6939
+ hicloud notify -t "Alert" -p "Database connection restored"
6480
6940
  `);
6481
6941
  return;
6482
6942
  }
6483
6943
  if (!message) {
6484
6944
  console.error(chalk.red('Error: Message is required. Use -p "your message" to specify the notification text.'));
6485
- console.log(chalk.gray('Run "happy-cloud notify --help" for usage information.'));
6945
+ console.log(chalk.gray('Run "hicloud notify --help" for usage information.'));
6486
6946
  process.exit(1);
6487
6947
  }
6488
6948
  let credentials = await readCredentials();
6489
6949
  if (!credentials) {
6490
- console.error(chalk.red('Error: Not authenticated. Please run "happy-cloud auth login" first.'));
6950
+ console.error(chalk.red('Error: Not authenticated. Please run "hicloud auth login" first.'));
6491
6951
  process.exit(1);
6492
6952
  }
6493
6953
  console.log(chalk.blue("\u{1F4F1} Sending push notification..."));
@@ -6513,4 +6973,4 @@ ${chalk.bold("Examples:")}
6513
6973
  }
6514
6974
  }
6515
6975
 
6516
- export { ExitCodeError as E, GEMINI_MODEL_ENV as G, createGeminiBackend as a, stopCaffeinate as b, createDefaultRuntimeShell as c, resolveCodexExecutable as d, shouldUseShellForCodex as e, getProjectPath as f, getInitialGeminiModel as g, claudeLocal as h, initialMachineMetadata as i, isBun as j, claudeCheckSession as k, getEnvironmentInfo as l, startCaffeinate as m, notifyDaemonSessionStarted as n, projectPath as p, readGeminiLocalConfig as r, saveGeminiModelToConfig as s, trimIdent as t };
6976
+ export { ExitCodeError as E, GEMINI_MODEL_ENV as G, createGeminiBackend as a, stopCaffeinate as b, createDefaultRuntimeShell as c, createCodexBackend as d, getProjectPath as e, formatDisplayMessage as f, getInitialGeminiModel as g, claudeLocal as h, initialMachineMetadata as i, isBun as j, trimIdent as k, claudeCheckSession as l, getEnvironmentInfo as m, notifyDaemonSessionStarted as n, startCaffeinate as o, projectPath as p, readGeminiLocalConfig as r, saveGeminiModelToConfig as s, truncateDisplayMessage as t, validateCodexAcpSpawn as v };