happy-imou-cloud 2.0.1 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BaseReasoningProcessor-DQE2l7Xu.mjs → BaseReasoningProcessor-B37yOHxo.mjs} +2 -2
- package/dist/{BaseReasoningProcessor-01KqA3Kz.cjs → BaseReasoningProcessor-_wxlqKB8.cjs} +4 -4
- package/dist/{api-B8v4tczT.cjs → api-D9dIR956.cjs} +97 -44
- package/dist/{api-B5Ui8Fw0.mjs → api-DpQIC-DJ.mjs} +56 -3
- package/dist/{command-D8yNlaDo.cjs → command-CdXv1zNF.cjs} +3 -3
- package/dist/{command-BfIuJmeo.mjs → command-DRqrBuHM.mjs} +3 -3
- package/dist/{index-BByhFIIq.mjs → index-CriPm_z9.mjs} +15 -17
- package/dist/{index-BOqJ9hwi.cjs → index-LYPXVO_L.cjs} +98 -100
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +3 -3
- package/dist/lib.cjs +1 -1
- package/dist/lib.d.cts +6 -0
- package/dist/lib.d.mts +6 -0
- package/dist/lib.mjs +1 -1
- package/dist/{persistence-CzpZpiL3.mjs → persistence-CqgPgbzN.mjs} +29 -7
- package/dist/{persistence-C33AMdtv.cjs → persistence-PzKU0QCa.cjs} +54 -32
- package/dist/{registerKillSessionHandler-BkzQulD9.cjs → registerKillSessionHandler-BDBPoQSA.cjs} +2 -2
- package/dist/{registerKillSessionHandler-BtSK7IOa.mjs → registerKillSessionHandler-C3M_-4Zg.mjs} +2 -2
- package/dist/{runClaude-C_WLfM6c.mjs → runClaude-D6Pdkevn.mjs} +250 -46
- package/dist/{runClaude-CNVufgZb.cjs → runClaude-IeRSC5qX.cjs} +270 -66
- package/dist/{runCodex-8eWjTPJr.mjs → runCodex-CsfUU1Wb.mjs} +216 -401
- package/dist/{runCodex-Dzy8anlX.cjs → runCodex-WRmgSK6L.cjs} +216 -401
- package/dist/{runGemini-nbr0mm-S.mjs → runGemini-CrH3dQ0Y.mjs} +5 -5
- package/dist/{runGemini-CgsVKP7m.cjs → runGemini-qBh6zs5G.cjs} +5 -5
- package/package.json +1 -2
- package/dist/future-Dq4Ha1Dn.cjs +0 -24
- package/dist/future-xRdLl3vf.mjs +0 -22
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
|
-
import { c as configuration, p as packageJson, s as startOfflineReconnection, l as logger } from './api-
|
|
4
|
-
import { p as projectPath } from './index-
|
|
3
|
+
import { c as configuration, p as packageJson, s as startOfflineReconnection, l as logger } from './api-DpQIC-DJ.mjs';
|
|
4
|
+
import { p as projectPath } from './index-CriPm_z9.mjs';
|
|
5
5
|
import { EventEmitter } from 'node:events';
|
|
6
6
|
import { randomUUID } from 'node:crypto';
|
|
7
7
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var os = require('node:os');
|
|
4
|
-
var
|
|
5
|
-
var api = require('./api-
|
|
6
|
-
var index = require('./index-
|
|
4
|
+
var node_path = require('node:path');
|
|
5
|
+
var api = require('./api-D9dIR956.cjs');
|
|
6
|
+
var index = require('./index-LYPXVO_L.cjs');
|
|
7
7
|
var node_events = require('node:events');
|
|
8
8
|
var node_crypto = require('node:crypto');
|
|
9
9
|
|
|
@@ -20,7 +20,7 @@ function createSessionMetadata(opts) {
|
|
|
20
20
|
homeDir: os.homedir(),
|
|
21
21
|
happyHomeDir: api.configuration.happyCloudHomeDir,
|
|
22
22
|
happyLibDir: index.projectPath(),
|
|
23
|
-
happyToolsDir:
|
|
23
|
+
happyToolsDir: node_path.resolve(index.projectPath(), "tools", "unpacked"),
|
|
24
24
|
startedFromDaemon: opts.startedBy === "daemon",
|
|
25
25
|
hostPid: process.pid,
|
|
26
26
|
startedBy: opts.startedBy || "terminal",
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var axios = require('axios');
|
|
4
4
|
var chalk = require('chalk');
|
|
5
|
-
var fs
|
|
6
|
-
var
|
|
5
|
+
var fs = require('fs');
|
|
6
|
+
var node_fs = require('node:fs');
|
|
7
7
|
var os = require('node:os');
|
|
8
|
-
var
|
|
8
|
+
var node_path = require('node:path');
|
|
9
9
|
var node_events = require('node:events');
|
|
10
10
|
var socket_ioClient = require('socket.io-client');
|
|
11
11
|
var z = require('zod');
|
|
@@ -13,13 +13,13 @@ var node_crypto = require('node:crypto');
|
|
|
13
13
|
var tweetnacl = require('tweetnacl');
|
|
14
14
|
var child_process = require('child_process');
|
|
15
15
|
var util = require('util');
|
|
16
|
-
var fs$
|
|
16
|
+
var fs$1 = require('fs/promises');
|
|
17
17
|
var crypto = require('crypto');
|
|
18
|
-
var path
|
|
18
|
+
var path = require('path');
|
|
19
19
|
var expoServerSdk = require('expo-server-sdk');
|
|
20
20
|
|
|
21
21
|
var name = "happy-imou-cloud";
|
|
22
|
-
var version = "2.0.
|
|
22
|
+
var version = "2.0.3";
|
|
23
23
|
var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
|
|
24
24
|
var author = "long.zhu";
|
|
25
25
|
var license = "MIT";
|
|
@@ -103,7 +103,6 @@ var scripts = {
|
|
|
103
103
|
};
|
|
104
104
|
var dependencies = {
|
|
105
105
|
"@agentclientprotocol/sdk": "^0.14.1",
|
|
106
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
107
106
|
"@stablelib/base64": "^2.0.1",
|
|
108
107
|
"@stablelib/hex": "^2.0.1",
|
|
109
108
|
"@types/cross-spawn": "^6.0.6",
|
|
@@ -218,7 +217,7 @@ class Configuration {
|
|
|
218
217
|
const expandedPath = process.env.HAPPY_CLOUD_HOME_DIR.replace(/^~/, os.homedir());
|
|
219
218
|
this.happyCloudHomeDir = expandedPath;
|
|
220
219
|
} else {
|
|
221
|
-
this.happyCloudHomeDir =
|
|
220
|
+
this.happyCloudHomeDir = node_path.join(os.homedir(), ".happy-cloud");
|
|
222
221
|
}
|
|
223
222
|
this.happyHomeDir = this.happyCloudHomeDir;
|
|
224
223
|
} else {
|
|
@@ -226,15 +225,15 @@ class Configuration {
|
|
|
226
225
|
const expandedPath = process.env.HAPPY_HOME_DIR.replace(/^~/, os.homedir());
|
|
227
226
|
this.happyHomeDir = expandedPath;
|
|
228
227
|
} else {
|
|
229
|
-
this.happyHomeDir =
|
|
228
|
+
this.happyHomeDir = node_path.join(os.homedir(), ".happy");
|
|
230
229
|
}
|
|
231
230
|
this.happyCloudHomeDir = this.happyHomeDir;
|
|
232
231
|
}
|
|
233
|
-
this.logsDir =
|
|
234
|
-
this.settingsFile =
|
|
235
|
-
this.privateKeyFile =
|
|
236
|
-
this.daemonStateFile =
|
|
237
|
-
this.daemonLockFile =
|
|
232
|
+
this.logsDir = node_path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "logs");
|
|
233
|
+
this.settingsFile = node_path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "settings.json");
|
|
234
|
+
this.privateKeyFile = node_path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "access.key");
|
|
235
|
+
this.daemonStateFile = node_path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "daemon.state.json");
|
|
236
|
+
this.daemonLockFile = node_path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "daemon.state.json.lock");
|
|
238
237
|
this.isExperimentalEnabled = ["true", "1", "yes"].includes(process.env.HAPPY_EXPERIMENTAL?.toLowerCase() || "");
|
|
239
238
|
this.disableCaffeinate = ["true", "1", "yes"].includes(process.env.HAPPY_DISABLE_CAFFEINATE?.toLowerCase() || "");
|
|
240
239
|
this.currentCliVersion = packageJson.version;
|
|
@@ -252,11 +251,11 @@ class Configuration {
|
|
|
252
251
|
}
|
|
253
252
|
}
|
|
254
253
|
const homeDir = this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir;
|
|
255
|
-
if (!
|
|
256
|
-
|
|
254
|
+
if (!node_fs.existsSync(homeDir)) {
|
|
255
|
+
node_fs.mkdirSync(homeDir, { recursive: true });
|
|
257
256
|
}
|
|
258
|
-
if (!
|
|
259
|
-
|
|
257
|
+
if (!node_fs.existsSync(this.logsDir)) {
|
|
258
|
+
node_fs.mkdirSync(this.logsDir, { recursive: true });
|
|
260
259
|
}
|
|
261
260
|
}
|
|
262
261
|
}
|
|
@@ -286,7 +285,7 @@ function createTimestampForLogEntry(date = /* @__PURE__ */ new Date()) {
|
|
|
286
285
|
function getSessionLogPath() {
|
|
287
286
|
const timestamp = createTimestampForFilename();
|
|
288
287
|
const filename = configuration.isDaemonProcess ? `${timestamp}-daemon.log` : `${timestamp}.log`;
|
|
289
|
-
return
|
|
288
|
+
return node_path.join(configuration.logsDir, filename);
|
|
290
289
|
}
|
|
291
290
|
class Logger {
|
|
292
291
|
constructor(logFilePath = getSessionLogPath()) {
|
|
@@ -411,7 +410,7 @@ class Logger {
|
|
|
411
410
|
});
|
|
412
411
|
}
|
|
413
412
|
try {
|
|
414
|
-
fs
|
|
413
|
+
fs.appendFileSync(this.logFilePath, logLine);
|
|
415
414
|
} catch (appendError) {
|
|
416
415
|
if (process.env.DEBUG) {
|
|
417
416
|
console.error("[DEV MODE ONLY THROWING] Failed to append to log file:", appendError);
|
|
@@ -424,24 +423,24 @@ let logger = new Logger();
|
|
|
424
423
|
async function listDaemonLogFiles(limit = 50) {
|
|
425
424
|
try {
|
|
426
425
|
const logsDir = configuration.logsDir;
|
|
427
|
-
if (!
|
|
426
|
+
if (!node_fs.existsSync(logsDir)) {
|
|
428
427
|
return [];
|
|
429
428
|
}
|
|
430
|
-
const logs =
|
|
431
|
-
const fullPath =
|
|
432
|
-
const stats =
|
|
429
|
+
const logs = node_fs.readdirSync(logsDir).filter((file) => file.endsWith("-daemon.log")).map((file) => {
|
|
430
|
+
const fullPath = node_path.join(logsDir, file);
|
|
431
|
+
const stats = node_fs.statSync(fullPath);
|
|
433
432
|
return { file, path: fullPath, modified: stats.mtime };
|
|
434
433
|
}).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
435
434
|
try {
|
|
436
|
-
const { readDaemonState } = await Promise.resolve().then(function () { return require('./persistence-
|
|
435
|
+
const { readDaemonState } = await Promise.resolve().then(function () { return require('./persistence-PzKU0QCa.cjs'); });
|
|
437
436
|
const state = await readDaemonState();
|
|
438
437
|
if (!state) {
|
|
439
438
|
return logs;
|
|
440
439
|
}
|
|
441
|
-
if (state.daemonLogPath &&
|
|
442
|
-
const stats =
|
|
440
|
+
if (state.daemonLogPath && node_fs.existsSync(state.daemonLogPath)) {
|
|
441
|
+
const stats = node_fs.statSync(state.daemonLogPath);
|
|
443
442
|
const persisted = {
|
|
444
|
-
file:
|
|
443
|
+
file: node_path.basename(state.daemonLogPath),
|
|
445
444
|
path: state.daemonLogPath,
|
|
446
445
|
modified: stats.mtime
|
|
447
446
|
};
|
|
@@ -854,8 +853,8 @@ class RpcHandlerManager {
|
|
|
854
853
|
}
|
|
855
854
|
|
|
856
855
|
function validatePath(targetPath, workingDirectory) {
|
|
857
|
-
const resolvedTarget = path
|
|
858
|
-
const resolvedWorkingDir = path
|
|
856
|
+
const resolvedTarget = path.resolve(workingDirectory, targetPath);
|
|
857
|
+
const resolvedWorkingDir = path.resolve(workingDirectory);
|
|
859
858
|
const targetNormalized = resolvedTarget.replace(/\\/g, "/");
|
|
860
859
|
const workingDirNormalized = resolvedWorkingDir.replace(/\\/g, "/");
|
|
861
860
|
process.platform === "win32" ? "\\" : "/";
|
|
@@ -941,7 +940,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
941
940
|
return { success: false, error: validation.error };
|
|
942
941
|
}
|
|
943
942
|
try {
|
|
944
|
-
const buffer = await fs$
|
|
943
|
+
const buffer = await fs$1.readFile(data.path);
|
|
945
944
|
const content = buffer.toString("base64");
|
|
946
945
|
return { success: true, content };
|
|
947
946
|
} catch (error) {
|
|
@@ -958,7 +957,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
958
957
|
try {
|
|
959
958
|
if (data.expectedHash !== null && data.expectedHash !== void 0) {
|
|
960
959
|
try {
|
|
961
|
-
const existingBuffer = await fs$
|
|
960
|
+
const existingBuffer = await fs$1.readFile(data.path);
|
|
962
961
|
const existingHash = crypto.createHash("sha256").update(existingBuffer).digest("hex");
|
|
963
962
|
if (existingHash !== data.expectedHash) {
|
|
964
963
|
return {
|
|
@@ -978,7 +977,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
978
977
|
}
|
|
979
978
|
} else {
|
|
980
979
|
try {
|
|
981
|
-
await fs$
|
|
980
|
+
await fs$1.stat(data.path);
|
|
982
981
|
return {
|
|
983
982
|
success: false,
|
|
984
983
|
error: "File already exists but was expected to be new"
|
|
@@ -991,7 +990,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
991
990
|
}
|
|
992
991
|
}
|
|
993
992
|
const buffer = Buffer.from(data.content, "base64");
|
|
994
|
-
await fs$
|
|
993
|
+
await fs$1.writeFile(data.path, buffer);
|
|
995
994
|
const hash = crypto.createHash("sha256").update(buffer).digest("hex");
|
|
996
995
|
return { success: true, hash };
|
|
997
996
|
} catch (error) {
|
|
@@ -1006,10 +1005,10 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
1006
1005
|
return { success: false, error: validation.error };
|
|
1007
1006
|
}
|
|
1008
1007
|
try {
|
|
1009
|
-
const entries = await fs$
|
|
1008
|
+
const entries = await fs$1.readdir(data.path, { withFileTypes: true });
|
|
1010
1009
|
const directoryEntries = await Promise.all(
|
|
1011
1010
|
entries.map(async (entry) => {
|
|
1012
|
-
const fullPath = path
|
|
1011
|
+
const fullPath = path.join(data.path, entry.name);
|
|
1013
1012
|
let type = "other";
|
|
1014
1013
|
let size;
|
|
1015
1014
|
let modified;
|
|
@@ -1019,7 +1018,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
1019
1018
|
type = "file";
|
|
1020
1019
|
}
|
|
1021
1020
|
try {
|
|
1022
|
-
const stats = await fs$
|
|
1021
|
+
const stats = await fs$1.stat(fullPath);
|
|
1023
1022
|
size = stats.size;
|
|
1024
1023
|
modified = stats.mtime.getTime();
|
|
1025
1024
|
} catch (error) {
|
|
@@ -1050,26 +1049,26 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
1050
1049
|
if (!validation.valid) {
|
|
1051
1050
|
return { success: false, error: validation.error };
|
|
1052
1051
|
}
|
|
1053
|
-
async function buildTree(path, name, currentDepth) {
|
|
1052
|
+
async function buildTree(path$1, name, currentDepth) {
|
|
1054
1053
|
try {
|
|
1055
|
-
const stats = await fs$
|
|
1054
|
+
const stats = await fs$1.stat(path$1);
|
|
1056
1055
|
const node = {
|
|
1057
1056
|
name,
|
|
1058
|
-
path,
|
|
1057
|
+
path: path$1,
|
|
1059
1058
|
type: stats.isDirectory() ? "directory" : "file",
|
|
1060
1059
|
size: stats.size,
|
|
1061
1060
|
modified: stats.mtime.getTime()
|
|
1062
1061
|
};
|
|
1063
1062
|
if (stats.isDirectory() && currentDepth < data.maxDepth) {
|
|
1064
|
-
const entries = await fs$
|
|
1063
|
+
const entries = await fs$1.readdir(path$1, { withFileTypes: true });
|
|
1065
1064
|
const children = [];
|
|
1066
1065
|
await Promise.all(
|
|
1067
1066
|
entries.map(async (entry) => {
|
|
1068
1067
|
if (entry.isSymbolicLink()) {
|
|
1069
|
-
logger.debug(`Skipping symlink: ${path
|
|
1068
|
+
logger.debug(`Skipping symlink: ${path.join(path$1, entry.name)}`);
|
|
1070
1069
|
return;
|
|
1071
1070
|
}
|
|
1072
|
-
const childPath = path
|
|
1071
|
+
const childPath = path.join(path$1, entry.name);
|
|
1073
1072
|
const childNode = await buildTree(childPath, entry.name, currentDepth + 1);
|
|
1074
1073
|
if (childNode) {
|
|
1075
1074
|
children.push(childNode);
|
|
@@ -1085,7 +1084,7 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
|
|
|
1085
1084
|
}
|
|
1086
1085
|
return node;
|
|
1087
1086
|
} catch (error) {
|
|
1088
|
-
logger.debug(`Failed to process ${path}:`, error instanceof Error ? error.message : String(error));
|
|
1087
|
+
logger.debug(`Failed to process ${path$1}:`, error instanceof Error ? error.message : String(error));
|
|
1089
1088
|
return null;
|
|
1090
1089
|
}
|
|
1091
1090
|
}
|
|
@@ -1362,6 +1361,8 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1362
1361
|
encryptionKey;
|
|
1363
1362
|
encryptionVariant;
|
|
1364
1363
|
pendingReliableCodexMessages = [];
|
|
1364
|
+
reconnectAfterServerDisconnectTimer = null;
|
|
1365
|
+
lastSocketServerError = null;
|
|
1365
1366
|
constructor(credentials, session) {
|
|
1366
1367
|
super();
|
|
1367
1368
|
this.credentials = credentials;
|
|
@@ -1396,6 +1397,8 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1396
1397
|
});
|
|
1397
1398
|
this.socket.on("connect", () => {
|
|
1398
1399
|
logger.debug("Socket connected successfully");
|
|
1400
|
+
this.clearReconnectAfterServerDisconnectTimer();
|
|
1401
|
+
this.lastSocketServerError = null;
|
|
1399
1402
|
this.rpcHandlerManager.onSocketConnect(this.socket);
|
|
1400
1403
|
this.flushReliableCodexMessages();
|
|
1401
1404
|
});
|
|
@@ -1405,6 +1408,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1405
1408
|
this.socket.on("disconnect", (reason) => {
|
|
1406
1409
|
logger.debug("[API] Socket disconnected:", reason);
|
|
1407
1410
|
this.rpcHandlerManager.onSocketDisconnect();
|
|
1411
|
+
this.retryAfterServerDisconnect(reason);
|
|
1408
1412
|
});
|
|
1409
1413
|
this.socket.on("connect_error", (error) => {
|
|
1410
1414
|
logger.debug("[API] Socket connection error:", error);
|
|
@@ -1452,6 +1456,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1452
1456
|
});
|
|
1453
1457
|
this.socket.on("error", (error) => {
|
|
1454
1458
|
logger.debug("[API] Socket error:", error);
|
|
1459
|
+
this.lastSocketServerError = this.normalizeSocketError(error);
|
|
1455
1460
|
});
|
|
1456
1461
|
this.socket.connect();
|
|
1457
1462
|
}
|
|
@@ -1723,6 +1728,7 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1723
1728
|
}
|
|
1724
1729
|
async close() {
|
|
1725
1730
|
logger.debug("[API] socket.close() called");
|
|
1731
|
+
this.clearReconnectAfterServerDisconnectTimer();
|
|
1726
1732
|
this.socket.close();
|
|
1727
1733
|
}
|
|
1728
1734
|
emitEncryptedSessionMessage(encrypted) {
|
|
@@ -1758,6 +1764,53 @@ class ApiSessionClient extends node_events.EventEmitter {
|
|
|
1758
1764
|
return false;
|
|
1759
1765
|
}
|
|
1760
1766
|
}
|
|
1767
|
+
retryAfterServerDisconnect(reason) {
|
|
1768
|
+
if (reason !== "io server disconnect") {
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
const errorCode = this.lastSocketServerError?.error;
|
|
1772
|
+
if (errorCode !== "REQUEST_EXPIRED" && errorCode !== "REQUEST_REPLAYED") {
|
|
1773
|
+
return;
|
|
1774
|
+
}
|
|
1775
|
+
if (this.reconnectAfterServerDisconnectTimer || this.socket.connected) {
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
logger.debug("[API] Scheduling manual reconnect after retryable server disconnect", {
|
|
1779
|
+
reason,
|
|
1780
|
+
errorCode,
|
|
1781
|
+
message: this.lastSocketServerError?.message
|
|
1782
|
+
});
|
|
1783
|
+
this.reconnectAfterServerDisconnectTimer = setTimeout(() => {
|
|
1784
|
+
this.reconnectAfterServerDisconnectTimer = null;
|
|
1785
|
+
if (this.socket.connected) {
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
logger.debug("[API] Retrying socket connection after server disconnect", {
|
|
1789
|
+
errorCode,
|
|
1790
|
+
message: this.lastSocketServerError?.message
|
|
1791
|
+
});
|
|
1792
|
+
this.socket.connect();
|
|
1793
|
+
}, 1e3);
|
|
1794
|
+
}
|
|
1795
|
+
clearReconnectAfterServerDisconnectTimer() {
|
|
1796
|
+
if (!this.reconnectAfterServerDisconnectTimer) {
|
|
1797
|
+
return;
|
|
1798
|
+
}
|
|
1799
|
+
clearTimeout(this.reconnectAfterServerDisconnectTimer);
|
|
1800
|
+
this.reconnectAfterServerDisconnectTimer = null;
|
|
1801
|
+
}
|
|
1802
|
+
normalizeSocketError(error) {
|
|
1803
|
+
if (!error || typeof error !== "object") {
|
|
1804
|
+
return null;
|
|
1805
|
+
}
|
|
1806
|
+
const candidate = error;
|
|
1807
|
+
const errorCode = typeof candidate.error === "string" ? candidate.error : void 0;
|
|
1808
|
+
const message = typeof candidate.message === "string" ? candidate.message : void 0;
|
|
1809
|
+
if (!errorCode && !message) {
|
|
1810
|
+
return null;
|
|
1811
|
+
}
|
|
1812
|
+
return { error: errorCode, message };
|
|
1813
|
+
}
|
|
1761
1814
|
}
|
|
1762
1815
|
function createAbortError() {
|
|
1763
1816
|
const error = new Error("The operation was aborted");
|
|
@@ -17,7 +17,7 @@ import { resolve, join as join$1 } from 'path';
|
|
|
17
17
|
import { Expo } from 'expo-server-sdk';
|
|
18
18
|
|
|
19
19
|
var name = "happy-imou-cloud";
|
|
20
|
-
var version = "2.0.
|
|
20
|
+
var version = "2.0.3";
|
|
21
21
|
var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
|
|
22
22
|
var author = "long.zhu";
|
|
23
23
|
var license = "MIT";
|
|
@@ -101,7 +101,6 @@ var scripts = {
|
|
|
101
101
|
};
|
|
102
102
|
var dependencies = {
|
|
103
103
|
"@agentclientprotocol/sdk": "^0.14.1",
|
|
104
|
-
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
105
104
|
"@stablelib/base64": "^2.0.1",
|
|
106
105
|
"@stablelib/hex": "^2.0.1",
|
|
107
106
|
"@types/cross-spawn": "^6.0.6",
|
|
@@ -431,7 +430,7 @@ async function listDaemonLogFiles(limit = 50) {
|
|
|
431
430
|
return { file, path: fullPath, modified: stats.mtime };
|
|
432
431
|
}).sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
433
432
|
try {
|
|
434
|
-
const { readDaemonState } = await import('./persistence-
|
|
433
|
+
const { readDaemonState } = await import('./persistence-CqgPgbzN.mjs');
|
|
435
434
|
const state = await readDaemonState();
|
|
436
435
|
if (!state) {
|
|
437
436
|
return logs;
|
|
@@ -1360,6 +1359,8 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1360
1359
|
encryptionKey;
|
|
1361
1360
|
encryptionVariant;
|
|
1362
1361
|
pendingReliableCodexMessages = [];
|
|
1362
|
+
reconnectAfterServerDisconnectTimer = null;
|
|
1363
|
+
lastSocketServerError = null;
|
|
1363
1364
|
constructor(credentials, session) {
|
|
1364
1365
|
super();
|
|
1365
1366
|
this.credentials = credentials;
|
|
@@ -1394,6 +1395,8 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1394
1395
|
});
|
|
1395
1396
|
this.socket.on("connect", () => {
|
|
1396
1397
|
logger.debug("Socket connected successfully");
|
|
1398
|
+
this.clearReconnectAfterServerDisconnectTimer();
|
|
1399
|
+
this.lastSocketServerError = null;
|
|
1397
1400
|
this.rpcHandlerManager.onSocketConnect(this.socket);
|
|
1398
1401
|
this.flushReliableCodexMessages();
|
|
1399
1402
|
});
|
|
@@ -1403,6 +1406,7 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1403
1406
|
this.socket.on("disconnect", (reason) => {
|
|
1404
1407
|
logger.debug("[API] Socket disconnected:", reason);
|
|
1405
1408
|
this.rpcHandlerManager.onSocketDisconnect();
|
|
1409
|
+
this.retryAfterServerDisconnect(reason);
|
|
1406
1410
|
});
|
|
1407
1411
|
this.socket.on("connect_error", (error) => {
|
|
1408
1412
|
logger.debug("[API] Socket connection error:", error);
|
|
@@ -1450,6 +1454,7 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1450
1454
|
});
|
|
1451
1455
|
this.socket.on("error", (error) => {
|
|
1452
1456
|
logger.debug("[API] Socket error:", error);
|
|
1457
|
+
this.lastSocketServerError = this.normalizeSocketError(error);
|
|
1453
1458
|
});
|
|
1454
1459
|
this.socket.connect();
|
|
1455
1460
|
}
|
|
@@ -1721,6 +1726,7 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1721
1726
|
}
|
|
1722
1727
|
async close() {
|
|
1723
1728
|
logger.debug("[API] socket.close() called");
|
|
1729
|
+
this.clearReconnectAfterServerDisconnectTimer();
|
|
1724
1730
|
this.socket.close();
|
|
1725
1731
|
}
|
|
1726
1732
|
emitEncryptedSessionMessage(encrypted) {
|
|
@@ -1756,6 +1762,53 @@ class ApiSessionClient extends EventEmitter {
|
|
|
1756
1762
|
return false;
|
|
1757
1763
|
}
|
|
1758
1764
|
}
|
|
1765
|
+
retryAfterServerDisconnect(reason) {
|
|
1766
|
+
if (reason !== "io server disconnect") {
|
|
1767
|
+
return;
|
|
1768
|
+
}
|
|
1769
|
+
const errorCode = this.lastSocketServerError?.error;
|
|
1770
|
+
if (errorCode !== "REQUEST_EXPIRED" && errorCode !== "REQUEST_REPLAYED") {
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
if (this.reconnectAfterServerDisconnectTimer || this.socket.connected) {
|
|
1774
|
+
return;
|
|
1775
|
+
}
|
|
1776
|
+
logger.debug("[API] Scheduling manual reconnect after retryable server disconnect", {
|
|
1777
|
+
reason,
|
|
1778
|
+
errorCode,
|
|
1779
|
+
message: this.lastSocketServerError?.message
|
|
1780
|
+
});
|
|
1781
|
+
this.reconnectAfterServerDisconnectTimer = setTimeout(() => {
|
|
1782
|
+
this.reconnectAfterServerDisconnectTimer = null;
|
|
1783
|
+
if (this.socket.connected) {
|
|
1784
|
+
return;
|
|
1785
|
+
}
|
|
1786
|
+
logger.debug("[API] Retrying socket connection after server disconnect", {
|
|
1787
|
+
errorCode,
|
|
1788
|
+
message: this.lastSocketServerError?.message
|
|
1789
|
+
});
|
|
1790
|
+
this.socket.connect();
|
|
1791
|
+
}, 1e3);
|
|
1792
|
+
}
|
|
1793
|
+
clearReconnectAfterServerDisconnectTimer() {
|
|
1794
|
+
if (!this.reconnectAfterServerDisconnectTimer) {
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1797
|
+
clearTimeout(this.reconnectAfterServerDisconnectTimer);
|
|
1798
|
+
this.reconnectAfterServerDisconnectTimer = null;
|
|
1799
|
+
}
|
|
1800
|
+
normalizeSocketError(error) {
|
|
1801
|
+
if (!error || typeof error !== "object") {
|
|
1802
|
+
return null;
|
|
1803
|
+
}
|
|
1804
|
+
const candidate = error;
|
|
1805
|
+
const errorCode = typeof candidate.error === "string" ? candidate.error : void 0;
|
|
1806
|
+
const message = typeof candidate.message === "string" ? candidate.message : void 0;
|
|
1807
|
+
if (!errorCode && !message) {
|
|
1808
|
+
return null;
|
|
1809
|
+
}
|
|
1810
|
+
return { error: errorCode, message };
|
|
1811
|
+
}
|
|
1759
1812
|
}
|
|
1760
1813
|
function createAbortError() {
|
|
1761
1814
|
const error = new Error("The operation was aborted");
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-LYPXVO_L.cjs');
|
|
4
4
|
require('chalk');
|
|
5
|
-
require('./api-
|
|
5
|
+
require('./api-D9dIR956.cjs');
|
|
6
6
|
require('axios');
|
|
7
7
|
require('fs');
|
|
8
8
|
require('node:fs');
|
|
@@ -19,7 +19,7 @@ require('fs/promises');
|
|
|
19
19
|
require('crypto');
|
|
20
20
|
require('path');
|
|
21
21
|
require('expo-server-sdk');
|
|
22
|
-
require('./persistence-
|
|
22
|
+
require('./persistence-PzKU0QCa.cjs');
|
|
23
23
|
require('node:fs/promises');
|
|
24
24
|
require('os');
|
|
25
25
|
require('tmp');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { c as createDefaultRuntimeShell } from './index-
|
|
1
|
+
import { c as createDefaultRuntimeShell } from './index-CriPm_z9.mjs';
|
|
2
2
|
import 'chalk';
|
|
3
|
-
import './api-
|
|
3
|
+
import './api-DpQIC-DJ.mjs';
|
|
4
4
|
import 'axios';
|
|
5
5
|
import 'fs';
|
|
6
6
|
import 'node:fs';
|
|
@@ -17,7 +17,7 @@ import 'fs/promises';
|
|
|
17
17
|
import 'crypto';
|
|
18
18
|
import 'path';
|
|
19
19
|
import 'expo-server-sdk';
|
|
20
|
-
import './persistence-
|
|
20
|
+
import './persistence-CqgPgbzN.mjs';
|
|
21
21
|
import 'node:fs/promises';
|
|
22
22
|
import 'os';
|
|
23
23
|
import 'tmp';
|
|
@@ -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, 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-
|
|
3
|
-
import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-
|
|
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-DpQIC-DJ.mjs';
|
|
3
|
+
import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-CqgPgbzN.mjs';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import fs from 'fs/promises';
|
|
6
6
|
import os, { homedir } from 'os';
|
|
@@ -3743,19 +3743,17 @@ function updateLocalGeminiCredentials(tokens) {
|
|
|
3743
3743
|
}
|
|
3744
3744
|
}
|
|
3745
3745
|
|
|
3746
|
-
function getProjectPath(workingDirectory) {
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
const projectId = resolved.replace(/[\\\/\.: _]/g, "-");
|
|
3752
|
-
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");
|
|
3753
3751
|
return join(claudeConfigDir, "projects", projectId);
|
|
3754
3752
|
}
|
|
3755
3753
|
|
|
3756
|
-
function claudeCheckSession(sessionId, path) {
|
|
3754
|
+
function claudeCheckSession(sessionId, path, transcriptPath) {
|
|
3757
3755
|
const projectDir = getProjectPath(path);
|
|
3758
|
-
const sessionFile = join(projectDir, `${sessionId}.jsonl`);
|
|
3756
|
+
const sessionFile = transcriptPath ?? join(projectDir, `${sessionId}.jsonl`);
|
|
3759
3757
|
const sessionExists = existsSync(sessionFile);
|
|
3760
3758
|
if (!sessionExists) {
|
|
3761
3759
|
logger.debug(`[claudeCheckSession] Path ${sessionFile} does not exist`);
|
|
@@ -6316,12 +6314,12 @@ async function ensureUnifiedDaemonStarted() {
|
|
|
6316
6314
|
async function executeUnifiedProvider(opts) {
|
|
6317
6315
|
const credentials = await ensureUnifiedRuntimePrerequisites(opts.credentials);
|
|
6318
6316
|
if (opts.provider === "claude") {
|
|
6319
|
-
const { runClaude } = await import('./runClaude-
|
|
6317
|
+
const { runClaude } = await import('./runClaude-D6Pdkevn.mjs');
|
|
6320
6318
|
await runClaude(credentials, opts.claudeOptions ?? {});
|
|
6321
6319
|
return;
|
|
6322
6320
|
}
|
|
6323
6321
|
if (opts.provider === "codex") {
|
|
6324
|
-
const { runCodex } = await import('./runCodex-
|
|
6322
|
+
const { runCodex } = await import('./runCodex-CsfUU1Wb.mjs');
|
|
6325
6323
|
await runCodex({
|
|
6326
6324
|
credentials,
|
|
6327
6325
|
startedBy: opts.startedBy,
|
|
@@ -6331,7 +6329,7 @@ async function executeUnifiedProvider(opts) {
|
|
|
6331
6329
|
return;
|
|
6332
6330
|
}
|
|
6333
6331
|
if (opts.provider === "gemini") {
|
|
6334
|
-
const { runGemini } = await import('./runGemini-
|
|
6332
|
+
const { runGemini } = await import('./runGemini-CrH3dQ0Y.mjs');
|
|
6335
6333
|
await runGemini({
|
|
6336
6334
|
credentials,
|
|
6337
6335
|
startedBy: opts.startedBy
|
|
@@ -6373,7 +6371,7 @@ function shouldRunMainClaudeFlow(opts) {
|
|
|
6373
6371
|
return;
|
|
6374
6372
|
} else if (subcommand === "runtime") {
|
|
6375
6373
|
if (args[1] === "providers") {
|
|
6376
|
-
const { renderRuntimeProviders } = await import('./command-
|
|
6374
|
+
const { renderRuntimeProviders } = await import('./command-DRqrBuHM.mjs');
|
|
6377
6375
|
console.log(renderRuntimeProviders());
|
|
6378
6376
|
return;
|
|
6379
6377
|
}
|
|
@@ -6551,8 +6549,8 @@ function shouldRunMainClaudeFlow(opts) {
|
|
|
6551
6549
|
const projectId = args[3];
|
|
6552
6550
|
try {
|
|
6553
6551
|
const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
|
|
6554
|
-
const { readCredentials: readCredentials2 } = await import('./persistence-
|
|
6555
|
-
const { ApiClient: ApiClient2 } = await import('./api-
|
|
6552
|
+
const { readCredentials: readCredentials2 } = await import('./persistence-CqgPgbzN.mjs');
|
|
6553
|
+
const { ApiClient: ApiClient2 } = await import('./api-DpQIC-DJ.mjs').then(function (n) { return n.q; });
|
|
6556
6554
|
let userEmail = void 0;
|
|
6557
6555
|
try {
|
|
6558
6556
|
const credentials = await readCredentials2();
|