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.
- package/dist/{config-cUle3acO.cjs → config-BQNrtwRY.cjs} +1 -1
- package/dist/{config-CW_20tNC.mjs → config-Dn99YH37.mjs} +1 -1
- package/dist/{index-CKUiwwxb.mjs → index-CUmYqKWt.mjs} +279 -156
- package/dist/{index-CInN1H_b.cjs → index-DVI4b0mv.cjs} +282 -159
- package/dist/index.cjs +4 -4
- package/dist/index.mjs +4 -4
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +32 -24
- package/dist/lib.d.mts +32 -24
- package/dist/lib.mjs +1 -1
- package/dist/{persistence-BXxnODRE.mjs → persistence-BGsuPqaO.mjs} +13 -3
- package/dist/{persistence-BmW5jAuU.cjs → persistence-BRH9F6RS.cjs} +13 -3
- package/dist/{runCodex-BKGgW5hO.cjs → runCodex-Cez8cuIh.cjs} +4 -4
- package/dist/{runCodex-DYoCy0rl.mjs → runCodex-X0BfjcZH.mjs} +4 -4
- package/dist/{runGemini-DPGUQNvu.mjs → runGemini-B-EK_BJQ.mjs} +5 -5
- package/dist/{runGemini-mbF04Hj9.cjs → runGemini-C3dDtGOV.cjs} +5 -5
- package/dist/{setupOfflineReconnection-D40K8dgt.mjs → setupOfflineReconnection-ndObLZk0.mjs} +2 -2
- package/dist/{setupOfflineReconnection-BFYzP7HT.cjs → setupOfflineReconnection-obypStdD.cjs} +2 -2
- package/dist/{types-DswSykEM.cjs → types-BSTmyv9d.cjs} +202 -66
- package/dist/{types-DB-rfqhR.mjs → types-BXyraW9R.mjs} +202 -68
- package/package.json +1 -1
|
@@ -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-
|
|
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-
|
|
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
|
|
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-
|
|
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-
|
|
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(
|
|
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(
|
|
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-
|
|
7620
|
-
const { readCredentials: readCredentials2 } = await import('./persistence-
|
|
7621
|
-
const { ApiClient: ApiClient2 } = await import('./types-
|
|
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-
|
|
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-
|
|
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);
|