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.
Files changed (27) hide show
  1. package/dist/{BaseReasoningProcessor-DQE2l7Xu.mjs → BaseReasoningProcessor-B37yOHxo.mjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-01KqA3Kz.cjs → BaseReasoningProcessor-_wxlqKB8.cjs} +4 -4
  3. package/dist/{api-B8v4tczT.cjs → api-D9dIR956.cjs} +97 -44
  4. package/dist/{api-B5Ui8Fw0.mjs → api-DpQIC-DJ.mjs} +56 -3
  5. package/dist/{command-D8yNlaDo.cjs → command-CdXv1zNF.cjs} +3 -3
  6. package/dist/{command-BfIuJmeo.mjs → command-DRqrBuHM.mjs} +3 -3
  7. package/dist/{index-BByhFIIq.mjs → index-CriPm_z9.mjs} +15 -17
  8. package/dist/{index-BOqJ9hwi.cjs → index-LYPXVO_L.cjs} +98 -100
  9. package/dist/index.cjs +3 -3
  10. package/dist/index.mjs +3 -3
  11. package/dist/lib.cjs +1 -1
  12. package/dist/lib.d.cts +6 -0
  13. package/dist/lib.d.mts +6 -0
  14. package/dist/lib.mjs +1 -1
  15. package/dist/{persistence-CzpZpiL3.mjs → persistence-CqgPgbzN.mjs} +29 -7
  16. package/dist/{persistence-C33AMdtv.cjs → persistence-PzKU0QCa.cjs} +54 -32
  17. package/dist/{registerKillSessionHandler-BkzQulD9.cjs → registerKillSessionHandler-BDBPoQSA.cjs} +2 -2
  18. package/dist/{registerKillSessionHandler-BtSK7IOa.mjs → registerKillSessionHandler-C3M_-4Zg.mjs} +2 -2
  19. package/dist/{runClaude-C_WLfM6c.mjs → runClaude-D6Pdkevn.mjs} +250 -46
  20. package/dist/{runClaude-CNVufgZb.cjs → runClaude-IeRSC5qX.cjs} +270 -66
  21. package/dist/{runCodex-8eWjTPJr.mjs → runCodex-CsfUU1Wb.mjs} +216 -401
  22. package/dist/{runCodex-Dzy8anlX.cjs → runCodex-WRmgSK6L.cjs} +216 -401
  23. package/dist/{runGemini-nbr0mm-S.mjs → runGemini-CrH3dQ0Y.mjs} +5 -5
  24. package/dist/{runGemini-CgsVKP7m.cjs → runGemini-qBh6zs5G.cjs} +5 -5
  25. package/package.json +1 -2
  26. package/dist/future-Dq4Ha1Dn.cjs +0 -24
  27. 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-B5Ui8Fw0.mjs';
4
- import { p as projectPath } from './index-BByhFIIq.mjs';
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 path = require('node:path');
5
- var api = require('./api-B8v4tczT.cjs');
6
- var index = require('./index-BOqJ9hwi.cjs');
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: path.resolve(index.projectPath(), "tools", "unpacked"),
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$1 = require('fs');
6
- var fs = require('node:fs');
5
+ var fs = require('fs');
6
+ var node_fs = require('node:fs');
7
7
  var os = require('node:os');
8
- var path = require('node:path');
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$2 = require('fs/promises');
16
+ var fs$1 = require('fs/promises');
17
17
  var crypto = require('crypto');
18
- var path$1 = require('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.1";
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 = path.join(os.homedir(), ".happy-cloud");
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 = path.join(os.homedir(), ".happy");
228
+ this.happyHomeDir = node_path.join(os.homedir(), ".happy");
230
229
  }
231
230
  this.happyCloudHomeDir = this.happyHomeDir;
232
231
  }
233
- this.logsDir = path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "logs");
234
- this.settingsFile = path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "settings.json");
235
- this.privateKeyFile = path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "access.key");
236
- this.daemonStateFile = path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "daemon.state.json");
237
- this.daemonLockFile = path.join(this.isHappyCloudMode ? this.happyCloudHomeDir : this.happyHomeDir, "daemon.state.json.lock");
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 (!fs.existsSync(homeDir)) {
256
- fs.mkdirSync(homeDir, { recursive: true });
254
+ if (!node_fs.existsSync(homeDir)) {
255
+ node_fs.mkdirSync(homeDir, { recursive: true });
257
256
  }
258
- if (!fs.existsSync(this.logsDir)) {
259
- fs.mkdirSync(this.logsDir, { recursive: true });
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 path.join(configuration.logsDir, filename);
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$1.appendFileSync(this.logFilePath, logLine);
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 (!fs.existsSync(logsDir)) {
426
+ if (!node_fs.existsSync(logsDir)) {
428
427
  return [];
429
428
  }
430
- const logs = fs.readdirSync(logsDir).filter((file) => file.endsWith("-daemon.log")).map((file) => {
431
- const fullPath = path.join(logsDir, file);
432
- const stats = fs.statSync(fullPath);
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-C33AMdtv.cjs'); });
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 && fs.existsSync(state.daemonLogPath)) {
442
- const stats = fs.statSync(state.daemonLogPath);
440
+ if (state.daemonLogPath && node_fs.existsSync(state.daemonLogPath)) {
441
+ const stats = node_fs.statSync(state.daemonLogPath);
443
442
  const persisted = {
444
- file: path.basename(state.daemonLogPath),
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$1.resolve(workingDirectory, targetPath);
858
- const resolvedWorkingDir = path$1.resolve(workingDirectory);
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$2.readFile(data.path);
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$2.readFile(data.path);
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$2.stat(data.path);
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$2.writeFile(data.path, buffer);
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$2.readdir(data.path, { withFileTypes: true });
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$1.join(data.path, entry.name);
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$2.stat(fullPath);
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$2.stat(path);
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$2.readdir(path, { withFileTypes: true });
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$1.join(path, entry.name)}`);
1068
+ logger.debug(`Skipping symlink: ${path.join(path$1, entry.name)}`);
1070
1069
  return;
1071
1070
  }
1072
- const childPath = path$1.join(path, entry.name);
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.1";
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-CzpZpiL3.mjs');
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-BOqJ9hwi.cjs');
3
+ var index = require('./index-LYPXVO_L.cjs');
4
4
  require('chalk');
5
- require('./api-B8v4tczT.cjs');
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-C33AMdtv.cjs');
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-BByhFIIq.mjs';
1
+ import { c as createDefaultRuntimeShell } from './index-CriPm_z9.mjs';
2
2
  import 'chalk';
3
- import './api-B5Ui8Fw0.mjs';
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-CzpZpiL3.mjs';
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-B5Ui8Fw0.mjs';
3
- import { writeCredentialsLegacy, writeCredentialsDataKey, readCredentials, readSettings, updateSettings, readDaemonState, clearDaemonState, acquireDaemonLock, writeDaemonState, releaseDaemonLock, validateProfileForAgent, getProfileEnvironmentVariables, clearCredentials, clearMachineId } from './persistence-CzpZpiL3.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-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
- let resolved = resolve$1(workingDirectory);
3748
- if (process.platform === "win32" && isAbsolute(resolved)) {
3749
- resolved = resolved.replace(/^[A-Z]:/i, "");
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-C_WLfM6c.mjs');
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-8eWjTPJr.mjs');
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-nbr0mm-S.mjs');
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-BfIuJmeo.mjs');
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-CzpZpiL3.mjs');
6555
- const { ApiClient: ApiClient2 } = await import('./api-B5Ui8Fw0.mjs').then(function (n) { return n.q; });
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();