happy-imou-cloud 1.1.5 → 1.1.7

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.
@@ -4,7 +4,7 @@ var fs = require('fs');
4
4
  var path = require('path');
5
5
  var os = require('os');
6
6
  var child_process = require('child_process');
7
- var api = require('./types-DswSykEM.cjs');
7
+ var api = require('./types-BSTmyv9d.cjs');
8
8
 
9
9
  const GEMINI_API_KEY_ENV = "GEMINI_API_KEY";
10
10
  const GOOGLE_API_KEY_ENV = "GOOGLE_API_KEY";
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { homedir } from 'os';
4
4
  import { execSync } from 'child_process';
5
- import { l as logger } from './types-DB-rfqhR.mjs';
5
+ import { l as logger } from './types-BXyraW9R.mjs';
6
6
 
7
7
  const GEMINI_API_KEY_ENV = "GEMINI_API_KEY";
8
8
  const GOOGLE_API_KEY_ENV = "GOOGLE_API_KEY";
@@ -1,7 +1,7 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
2
  import os$1, { homedir, tmpdir } from 'node:os';
3
3
  import { randomUUID, randomBytes } from 'node:crypto';
4
- import { l as logger, f as backoff, d as delay, R as RawJSONLinesSchema, g as AsyncLock, c as configuration, p as packageJson, e as encodeBase64, h as encodeBase64Url, i as decodeBase64, H as HAPPY_CLOUD_DAEMON_PORT, A as ApiClient, b as connectionState, s as startOfflineReconnection, j as getLatestDaemonLog } from './types-DB-rfqhR.mjs';
4
+ import { l as logger, f as backoff, d as delay, R as RawJSONLinesSchema, g as AsyncLock, c as configuration, H as HAPPY_CLOUD_DAEMON_PORT, p as packageJson, e as encodeBase64, h as buildAuthenticatedHeaders, i as encodeBase64Url, j as buildClientHeaders, k as decodeBase64, A as ApiClient, b as connectionState, s as startOfflineReconnection, m as getLatestDaemonLog } from './types-BXyraW9R.mjs';
5
5
  import { spawn, execSync, execFileSync } from 'node:child_process';
6
6
  import { resolve, isAbsolute, join } from 'node:path';
7
7
  import { createInterface } from 'node:readline';
@@ -19,7 +19,7 @@ import 'socket.io-client';
19
19
  import tweetnacl from 'tweetnacl';
20
20
  import 'expo-server-sdk';
21
21
  import { isDeepStrictEqual } from 'node:util';
22
- import { readDaemonState, clearDaemonState, readSettings, readCredentials, updateSettings, writeCredentialsLegacy, writeCredentialsDataKey, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-BXxnODRE.mjs';
22
+ import { readDaemonState, clearDaemonState, readSettings, readCredentials, updateSettings, writeCredentialsLegacy, writeCredentialsDataKey, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-BGsuPqaO.mjs';
23
23
  import { createHash, randomBytes as randomBytes$1 } from 'crypto';
24
24
  import { spawn as spawn$1, execSync as execSync$1, exec } from 'child_process';
25
25
  import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync as writeFileSync$1, chmodSync, unlinkSync as unlinkSync$1, mkdirSync as mkdirSync$1 } from 'fs';
@@ -3673,150 +3673,6 @@ function extractSDKMetadataAsync(onComplete) {
3673
3673
  });
3674
3674
  }
3675
3675
 
3676
- async function daemonPost(path, body) {
3677
- const state = await readDaemonState();
3678
- if (!state?.httpPort) {
3679
- const errorMessage = "No daemon running, no state file found";
3680
- logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3681
- return {
3682
- error: errorMessage
3683
- };
3684
- }
3685
- try {
3686
- process.kill(state.pid, 0);
3687
- } catch (error) {
3688
- const errorMessage = "Daemon is not running, file is stale";
3689
- logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3690
- return {
3691
- error: errorMessage
3692
- };
3693
- }
3694
- try {
3695
- const timeout = process.env.HAPPY_DAEMON_HTTP_TIMEOUT ? parseInt(process.env.HAPPY_DAEMON_HTTP_TIMEOUT) : 1e4;
3696
- const response = await fetch(`http://127.0.0.1:${state.httpPort}${path}`, {
3697
- method: "POST",
3698
- headers: { "Content-Type": "application/json" },
3699
- body: JSON.stringify(body || {}),
3700
- // Mostly increased for stress test
3701
- signal: AbortSignal.timeout(timeout)
3702
- });
3703
- if (!response.ok) {
3704
- const errorMessage = `Request failed: ${path}, HTTP ${response.status}`;
3705
- logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3706
- return {
3707
- error: errorMessage
3708
- };
3709
- }
3710
- return await response.json();
3711
- } catch (error) {
3712
- const errorMessage = `Request failed: ${path}, ${error instanceof Error ? error.message : "Unknown error"}`;
3713
- logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3714
- return {
3715
- error: errorMessage
3716
- };
3717
- }
3718
- }
3719
- async function notifyDaemonSessionStarted(sessionId, metadata) {
3720
- return await daemonPost("/session-started", {
3721
- sessionId,
3722
- metadata
3723
- });
3724
- }
3725
- async function listDaemonSessions() {
3726
- const result = await daemonPost("/list");
3727
- return result.children || [];
3728
- }
3729
- async function stopDaemonSession(sessionId) {
3730
- const result = await daemonPost("/stop-session", { sessionId });
3731
- return result.success || false;
3732
- }
3733
- async function stopDaemonHttp() {
3734
- await daemonPost("/stop");
3735
- }
3736
- async function checkIfDaemonRunningAndCleanupStaleState() {
3737
- const state = await readDaemonState();
3738
- if (!state) {
3739
- return false;
3740
- }
3741
- try {
3742
- process.kill(state.pid, 0);
3743
- return true;
3744
- } catch {
3745
- logger.debug("[DAEMON RUN] Daemon PID not running, cleaning up state");
3746
- await cleanupDaemonState();
3747
- return false;
3748
- }
3749
- }
3750
- async function isDaemonRunningCurrentlyInstalledHappyVersion() {
3751
- logger.debug("[DAEMON CONTROL] Checking if daemon is running same version");
3752
- const runningDaemon = await checkIfDaemonRunningAndCleanupStaleState();
3753
- if (!runningDaemon) {
3754
- logger.debug("[DAEMON CONTROL] No daemon running, returning false");
3755
- return false;
3756
- }
3757
- const state = await readDaemonState();
3758
- if (!state) {
3759
- logger.debug("[DAEMON CONTROL] No daemon state found, returning false");
3760
- return false;
3761
- }
3762
- try {
3763
- const packageJsonPath = join$1(projectPath(), "package.json");
3764
- const packageJson = JSON.parse(readFileSync$1(packageJsonPath, "utf-8"));
3765
- const currentCliVersion = packageJson.version;
3766
- logger.debug(`[DAEMON CONTROL] Current CLI version: ${currentCliVersion}, Daemon started with version: ${state.startedWithCliVersion}`);
3767
- return currentCliVersion === state.startedWithCliVersion;
3768
- } catch (error) {
3769
- logger.debug("[DAEMON CONTROL] Error checking daemon version", error);
3770
- return false;
3771
- }
3772
- }
3773
- async function cleanupDaemonState() {
3774
- try {
3775
- await clearDaemonState();
3776
- logger.debug("[DAEMON RUN] Daemon state file removed");
3777
- } catch (error) {
3778
- logger.debug("[DAEMON RUN] Error cleaning up daemon metadata", error);
3779
- }
3780
- }
3781
- async function stopDaemon() {
3782
- try {
3783
- const state = await readDaemonState();
3784
- if (!state) {
3785
- logger.debug("No daemon state found");
3786
- return;
3787
- }
3788
- logger.debug(`Stopping daemon with PID ${state.pid}`);
3789
- try {
3790
- await stopDaemonHttp();
3791
- await waitForProcessDeath(state.pid, 2e3);
3792
- logger.debug("Daemon stopped gracefully via HTTP");
3793
- return;
3794
- } catch (error) {
3795
- logger.debug("HTTP stop failed, will force kill", error);
3796
- }
3797
- try {
3798
- process.kill(state.pid, "SIGKILL");
3799
- logger.debug("Force killed daemon");
3800
- } catch (error) {
3801
- logger.debug("Daemon already dead");
3802
- }
3803
- } catch (error) {
3804
- logger.debug("Error stopping daemon", error);
3805
- }
3806
- }
3807
- async function waitForProcessDeath(pid, timeout) {
3808
- const start = Date.now();
3809
- while (Date.now() - start < timeout) {
3810
- try {
3811
- process.kill(pid, 0);
3812
- await new Promise((resolve) => setTimeout(resolve, 100));
3813
- } catch {
3814
- return;
3815
- }
3816
- }
3817
- throw new Error("Process did not die within timeout");
3818
- }
3819
-
3820
3676
  function getDaemonPid() {
3821
3677
  try {
3822
3678
  if (!existsSync(configuration.daemonStateFile)) {
@@ -3984,6 +3840,210 @@ async function killRunawayHappyProcesses() {
3984
3840
  return { killed, errors };
3985
3841
  }
3986
3842
 
3843
+ async function daemonPost(path, body) {
3844
+ const state = await readDaemonState();
3845
+ if (!state?.httpPort) {
3846
+ const errorMessage = "No daemon running, no state file found";
3847
+ logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3848
+ return {
3849
+ error: errorMessage
3850
+ };
3851
+ }
3852
+ try {
3853
+ process.kill(state.pid, 0);
3854
+ } catch (error) {
3855
+ const errorMessage = "Daemon is not running, file is stale";
3856
+ logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3857
+ return {
3858
+ error: errorMessage
3859
+ };
3860
+ }
3861
+ try {
3862
+ const timeout = process.env.HAPPY_DAEMON_HTTP_TIMEOUT ? parseInt(process.env.HAPPY_DAEMON_HTTP_TIMEOUT) : 1e4;
3863
+ const response = await fetch(`http://127.0.0.1:${state.httpPort}${path}`, {
3864
+ method: "POST",
3865
+ headers: { "Content-Type": "application/json" },
3866
+ body: JSON.stringify(body || {}),
3867
+ // Mostly increased for stress test
3868
+ signal: AbortSignal.timeout(timeout)
3869
+ });
3870
+ if (!response.ok) {
3871
+ const errorMessage = `Request failed: ${path}, HTTP ${response.status}`;
3872
+ logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3873
+ return {
3874
+ error: errorMessage
3875
+ };
3876
+ }
3877
+ return await response.json();
3878
+ } catch (error) {
3879
+ const errorMessage = `Request failed: ${path}, ${error instanceof Error ? error.message : "Unknown error"}`;
3880
+ logger.debug(`[CONTROL CLIENT] ${errorMessage}`);
3881
+ return {
3882
+ error: errorMessage
3883
+ };
3884
+ }
3885
+ }
3886
+ async function stopDaemonOnKnownPort() {
3887
+ try {
3888
+ const timeout = process.env.HAPPY_DAEMON_HTTP_TIMEOUT ? parseInt(process.env.HAPPY_DAEMON_HTTP_TIMEOUT) : 2e3;
3889
+ const response = await fetch(`http://127.0.0.1:${HAPPY_CLOUD_DAEMON_PORT}/stop`, {
3890
+ method: "POST",
3891
+ headers: { "Content-Type": "application/json" },
3892
+ body: JSON.stringify({}),
3893
+ signal: AbortSignal.timeout(timeout)
3894
+ });
3895
+ if (!response.ok) {
3896
+ logger.debug(`[CONTROL CLIENT] Known daemon port stop failed with HTTP ${response.status}`);
3897
+ return false;
3898
+ }
3899
+ return true;
3900
+ } catch (error) {
3901
+ logger.debug("[CONTROL CLIENT] No reachable daemon on known control port", error);
3902
+ return false;
3903
+ }
3904
+ }
3905
+ async function killOrphanDaemonProcesses() {
3906
+ const daemonTypes = /* @__PURE__ */ new Set([
3907
+ "daemon",
3908
+ "dev-daemon",
3909
+ "daemon-version-check",
3910
+ "dev-daemon-version-check"
3911
+ ]);
3912
+ const orphanDaemons = (await findAllHappyProcesses()).filter(
3913
+ (proc) => proc.pid !== process.pid && daemonTypes.has(proc.type)
3914
+ );
3915
+ if (orphanDaemons.length === 0) {
3916
+ logger.debug("[CONTROL CLIENT] No orphan daemon processes found");
3917
+ return false;
3918
+ }
3919
+ let killed = false;
3920
+ for (const proc of orphanDaemons) {
3921
+ try {
3922
+ if (process.platform === "win32") {
3923
+ execFileSync("taskkill", ["/F", "/PID", proc.pid.toString()], { stdio: "ignore" });
3924
+ } else {
3925
+ process.kill(proc.pid, "SIGKILL");
3926
+ }
3927
+ logger.debug(`[CONTROL CLIENT] Killed orphan daemon PID ${proc.pid}: ${proc.command}`);
3928
+ killed = true;
3929
+ } catch (error) {
3930
+ logger.debug(`[CONTROL CLIENT] Failed to kill orphan daemon PID ${proc.pid}`, error);
3931
+ }
3932
+ }
3933
+ return killed;
3934
+ }
3935
+ async function notifyDaemonSessionStarted(sessionId, metadata) {
3936
+ return await daemonPost("/session-started", {
3937
+ sessionId,
3938
+ metadata
3939
+ });
3940
+ }
3941
+ async function listDaemonSessions() {
3942
+ const result = await daemonPost("/list");
3943
+ return result.children || [];
3944
+ }
3945
+ async function stopDaemonSession(sessionId) {
3946
+ const result = await daemonPost("/stop-session", { sessionId });
3947
+ return result.success || false;
3948
+ }
3949
+ async function stopDaemonHttp() {
3950
+ await daemonPost("/stop");
3951
+ }
3952
+ async function checkIfDaemonRunningAndCleanupStaleState() {
3953
+ const state = await readDaemonState();
3954
+ if (!state) {
3955
+ return false;
3956
+ }
3957
+ try {
3958
+ process.kill(state.pid, 0);
3959
+ return true;
3960
+ } catch {
3961
+ logger.debug("[DAEMON RUN] Daemon PID not running, cleaning up state");
3962
+ await cleanupDaemonState();
3963
+ return false;
3964
+ }
3965
+ }
3966
+ async function isDaemonRunningCurrentlyInstalledHappyVersion() {
3967
+ logger.debug("[DAEMON CONTROL] Checking if daemon is running same version");
3968
+ const runningDaemon = await checkIfDaemonRunningAndCleanupStaleState();
3969
+ if (!runningDaemon) {
3970
+ logger.debug("[DAEMON CONTROL] No daemon running, returning false");
3971
+ return false;
3972
+ }
3973
+ const state = await readDaemonState();
3974
+ if (!state) {
3975
+ logger.debug("[DAEMON CONTROL] No daemon state found, returning false");
3976
+ return false;
3977
+ }
3978
+ try {
3979
+ const packageJsonPath = join$1(projectPath(), "package.json");
3980
+ const packageJson = JSON.parse(readFileSync$1(packageJsonPath, "utf-8"));
3981
+ const currentCliVersion = packageJson.version;
3982
+ logger.debug(`[DAEMON CONTROL] Current CLI version: ${currentCliVersion}, Daemon started with version: ${state.startedWithCliVersion}`);
3983
+ return currentCliVersion === state.startedWithCliVersion;
3984
+ } catch (error) {
3985
+ logger.debug("[DAEMON CONTROL] Error checking daemon version", error);
3986
+ return false;
3987
+ }
3988
+ }
3989
+ async function cleanupDaemonState() {
3990
+ try {
3991
+ await clearDaemonState();
3992
+ logger.debug("[DAEMON RUN] Daemon state file removed");
3993
+ } catch (error) {
3994
+ logger.debug("[DAEMON RUN] Error cleaning up daemon metadata", error);
3995
+ }
3996
+ }
3997
+ async function stopDaemon() {
3998
+ try {
3999
+ const state = await readDaemonState();
4000
+ if (!state) {
4001
+ logger.debug("No daemon state found, trying known control port");
4002
+ const stoppedByKnownPort = await stopDaemonOnKnownPort();
4003
+ if (stoppedByKnownPort) {
4004
+ logger.debug(`Requested daemon stop via known control port ${HAPPY_CLOUD_DAEMON_PORT}`);
4005
+ return;
4006
+ }
4007
+ const killedOrphans = await killOrphanDaemonProcesses();
4008
+ if (killedOrphans) {
4009
+ logger.debug("Killed orphan daemon processes without state file");
4010
+ return;
4011
+ }
4012
+ logger.debug("No daemon state found");
4013
+ return;
4014
+ }
4015
+ logger.debug(`Stopping daemon with PID ${state.pid}`);
4016
+ try {
4017
+ await stopDaemonHttp();
4018
+ await waitForProcessDeath(state.pid, 2e3);
4019
+ logger.debug("Daemon stopped gracefully via HTTP");
4020
+ return;
4021
+ } catch (error) {
4022
+ logger.debug("HTTP stop failed, will force kill", error);
4023
+ }
4024
+ try {
4025
+ process.kill(state.pid, "SIGKILL");
4026
+ logger.debug("Force killed daemon");
4027
+ } catch (error) {
4028
+ logger.debug("Daemon already dead");
4029
+ }
4030
+ } catch (error) {
4031
+ logger.debug("Error stopping daemon", error);
4032
+ }
4033
+ }
4034
+ async function waitForProcessDeath(pid, timeout) {
4035
+ const start = Date.now();
4036
+ while (Date.now() - start < timeout) {
4037
+ try {
4038
+ process.kill(pid, 0);
4039
+ await new Promise((resolve) => setTimeout(resolve, 100));
4040
+ } catch {
4041
+ return;
4042
+ }
4043
+ }
4044
+ throw new Error("Process did not die within timeout");
4045
+ }
4046
+
3987
4047
  function getEnvironmentInfo() {
3988
4048
  return {
3989
4049
  PWD: process.env.PWD,
@@ -4067,6 +4127,7 @@ async function runDoctorCommand(filter) {
4067
4127
  const credentials = await readCredentials();
4068
4128
  if (credentials) {
4069
4129
  console.log(chalk.green("\u2713 Authenticated (credentials found)"));
4130
+ console.log(`Request signing: ${credentials.signing ? chalk.green("ready") : chalk.yellow("legacy credentials")}`);
4070
4131
  } else {
4071
4132
  console.log(chalk.yellow("\u26A0\uFE0F Not authenticated (no credentials)"));
4072
4133
  }
@@ -4394,6 +4455,8 @@ async function createTerminalAuthRequest(keypair) {
4394
4455
  const response = await axios.post(`${configuration.serverUrl}/v1/auth/request`, {
4395
4456
  publicKey: encodeBase64(keypair.publicKey),
4396
4457
  supportsV2: true
4458
+ }, {
4459
+ headers: buildClientHeaders()
4397
4460
  });
4398
4461
  if (process.env.DEBUG) {
4399
4462
  console.log("[AUTH DEBUG] Auth request sent successfully");
@@ -4662,6 +4725,7 @@ async function authAndSetupMachineIfNeeded() {
4662
4725
  } else {
4663
4726
  logger.debug("[AUTH] Using existing credentials");
4664
4727
  }
4728
+ credentials = await ensureSigningCredentials(credentials);
4665
4729
  const settings = await updateSettings(async (s) => {
4666
4730
  if (newAuth || !s.machineId) {
4667
4731
  return {
@@ -4674,6 +4738,53 @@ async function authAndSetupMachineIfNeeded() {
4674
4738
  logger.debug(`[AUTH] Machine ID: ${settings.machineId}`);
4675
4739
  return { credentials, machineId: settings.machineId };
4676
4740
  }
4741
+ async function ensureSigningCredentials(credentials) {
4742
+ if (credentials.signing) {
4743
+ return credentials;
4744
+ }
4745
+ try {
4746
+ const response = await axios.post(`${configuration.serverUrl}/v1/auth/refresh`, {}, {
4747
+ headers: buildAuthenticatedHeaders({
4748
+ credentials,
4749
+ method: "POST",
4750
+ url: `${configuration.serverUrl}/v1/auth/refresh`,
4751
+ body: {},
4752
+ headers: {
4753
+ "Content-Type": "application/json"
4754
+ },
4755
+ signRequest: false
4756
+ })
4757
+ });
4758
+ if (!response.data?.success || !response.data?.token || !response.data?.signing) {
4759
+ logger.debug("[AUTH] Signing bootstrap returned incomplete payload");
4760
+ return credentials;
4761
+ }
4762
+ const upgradedCredentials = {
4763
+ ...credentials,
4764
+ token: response.data.token,
4765
+ signing: response.data.signing
4766
+ };
4767
+ if (upgradedCredentials.encryption.type === "legacy") {
4768
+ await writeCredentialsLegacy({
4769
+ secret: upgradedCredentials.encryption.secret,
4770
+ token: upgradedCredentials.token,
4771
+ signing: upgradedCredentials.signing
4772
+ });
4773
+ } else {
4774
+ await writeCredentialsDataKey({
4775
+ publicKey: upgradedCredentials.encryption.publicKey,
4776
+ machineKey: upgradedCredentials.encryption.machineKey,
4777
+ token: upgradedCredentials.token,
4778
+ signing: upgradedCredentials.signing
4779
+ });
4780
+ }
4781
+ logger.debug("[AUTH] Signing credentials bootstrapped successfully");
4782
+ return upgradedCredentials;
4783
+ } catch (error) {
4784
+ logger.debug("[AUTH] Failed to bootstrap signing credentials", error);
4785
+ return credentials;
4786
+ }
4787
+ }
4677
4788
 
4678
4789
  function spawnHappyCLI(args, options = {}) {
4679
4790
  const projectRoot = projectPath();
@@ -6780,6 +6891,7 @@ async function handleAuthStatus() {
6780
6891
  console.log(chalk.green("\u2713 Authenticated"));
6781
6892
  const tokenPreview = credentials.token.substring(0, 30) + "...";
6782
6893
  console.log(chalk.gray(` Token: ${tokenPreview}`));
6894
+ console.log(chalk.gray(` Request signing: ${credentials.signing ? "ready" : "legacy credentials (will auto-upgrade on use)"}`));
6783
6895
  if (settings?.machineId) {
6784
6896
  console.log(chalk.green("\u2713 Machine registered"));
6785
6897
  console.log(chalk.gray(` Machine ID: ${settings.machineId}`));
@@ -7523,7 +7635,7 @@ function getVersionString() {
7523
7635
  return;
7524
7636
  } else if (subcommand === "codex") {
7525
7637
  try {
7526
- const { runCodex } = await import('./runCodex-DYoCy0rl.mjs');
7638
+ const { runCodex } = await import('./runCodex-X0BfjcZH.mjs');
7527
7639
  let startedBy = void 0;
7528
7640
  for (let i = 1; i < args.length; i++) {
7529
7641
  if (args[i] === "--started-by") {
@@ -7553,7 +7665,7 @@ function getVersionString() {
7553
7665
  process.exit(1);
7554
7666
  }
7555
7667
  try {
7556
- const { existsSync, readFileSync, writeFileSync, mkdirSync } = require("fs");
7668
+ const { existsSync, readFileSync: readFileSync2, writeFileSync, mkdirSync } = require("fs");
7557
7669
  const { join } = require("path");
7558
7670
  const { homedir } = require("os");
7559
7671
  const configDir = join(homedir(), ".gemini");
@@ -7564,7 +7676,7 @@ function getVersionString() {
7564
7676
  let config = {};
7565
7677
  if (existsSync(configPath)) {
7566
7678
  try {
7567
- config = JSON.parse(readFileSync(configPath, "utf-8"));
7679
+ config = JSON.parse(readFileSync2(configPath, "utf-8"));
7568
7680
  } catch (error) {
7569
7681
  config = {};
7570
7682
  }
@@ -7582,7 +7694,7 @@ function getVersionString() {
7582
7694
  }
7583
7695
  if (geminiSubcommand === "model" && args[2] === "get") {
7584
7696
  try {
7585
- const { existsSync, readFileSync } = require("fs");
7697
+ const { existsSync, readFileSync: readFileSync2 } = require("fs");
7586
7698
  const { join } = require("path");
7587
7699
  const { homedir } = require("os");
7588
7700
  const configPaths = [
@@ -7593,7 +7705,7 @@ function getVersionString() {
7593
7705
  for (const configPath of configPaths) {
7594
7706
  if (existsSync(configPath)) {
7595
7707
  try {
7596
- const config = JSON.parse(readFileSync(configPath, "utf-8"));
7708
+ const config = JSON.parse(readFileSync2(configPath, "utf-8"));
7597
7709
  model = config.model || config.GEMINI_MODEL || null;
7598
7710
  if (model) break;
7599
7711
  } catch (error) {
@@ -7616,9 +7728,9 @@ function getVersionString() {
7616
7728
  if (geminiSubcommand === "project" && args[2] === "set" && args[3]) {
7617
7729
  const projectId = args[3];
7618
7730
  try {
7619
- const { saveGoogleCloudProjectToConfig } = await import('./config-CW_20tNC.mjs').then(function (n) { return n.e; });
7620
- const { readCredentials: readCredentials2 } = await import('./persistence-BXxnODRE.mjs');
7621
- const { ApiClient: ApiClient2 } = await import('./types-DB-rfqhR.mjs').then(function (n) { return n.k; });
7731
+ const { saveGoogleCloudProjectToConfig } = await import('./config-Dn99YH37.mjs').then(function (n) { return n.e; });
7732
+ const { readCredentials: readCredentials2 } = await import('./persistence-BGsuPqaO.mjs');
7733
+ const { ApiClient: ApiClient2 } = await import('./types-BXyraW9R.mjs').then(function (n) { return n.n; });
7622
7734
  let userEmail = void 0;
7623
7735
  try {
7624
7736
  const credentials = await readCredentials2();
@@ -7649,7 +7761,7 @@ function getVersionString() {
7649
7761
  }
7650
7762
  if (geminiSubcommand === "project" && args[2] === "get") {
7651
7763
  try {
7652
- const { readGeminiLocalConfig } = await import('./config-CW_20tNC.mjs').then(function (n) { return n.e; });
7764
+ const { readGeminiLocalConfig } = await import('./config-Dn99YH37.mjs').then(function (n) { return n.e; });
7653
7765
  const config = readGeminiLocalConfig();
7654
7766
  if (config.googleCloudProject) {
7655
7767
  console.log(`Current Google Cloud Project: ${config.googleCloudProject}`);
@@ -7689,7 +7801,7 @@ function getVersionString() {
7689
7801
  process.exit(0);
7690
7802
  }
7691
7803
  try {
7692
- const { runGemini } = await import('./runGemini-DPGUQNvu.mjs');
7804
+ const { runGemini } = await import('./runGemini-B-EK_BJQ.mjs');
7693
7805
  let startedBy = void 0;
7694
7806
  for (let i = 1; i < args.length; i++) {
7695
7807
  if (args[i] === "--started-by") {
@@ -7789,6 +7901,17 @@ function getVersionString() {
7789
7901
  console.log("Daemon started successfully");
7790
7902
  } else {
7791
7903
  console.error("Failed to start daemon");
7904
+ const latest = await getLatestDaemonLog();
7905
+ if (latest) {
7906
+ console.error(`Latest daemon log: ${latest.path}`);
7907
+ try {
7908
+ const logContent = readFileSync(latest.path, "utf-8");
7909
+ if (logContent.includes("EADDRINUSE")) {
7910
+ console.error("Daemon control port is already in use. Retry after stopping the stale daemon or run `hicloud doctor clean`.");
7911
+ }
7912
+ } catch {
7913
+ }
7914
+ }
7792
7915
  process.exit(1);
7793
7916
  }
7794
7917
  process.exit(0);