happy-imou-cloud 2.0.10 → 2.0.11

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 (34) hide show
  1. package/dist/BaseReasoningProcessor-5ACv9gKu.mjs +320 -0
  2. package/dist/BaseReasoningProcessor-COrRWyn0.cjs +323 -0
  3. package/dist/ProviderSelectionHandler-BljOLMQn.mjs +261 -0
  4. package/dist/ProviderSelectionHandler-DBGobhGZ.cjs +265 -0
  5. package/dist/{api-BjxmW-0W.mjs → api-BcWf5v4i.mjs} +174 -46
  6. package/dist/{api-DUE5TJBE.cjs → api-Ye-rPX6s.cjs} +174 -46
  7. package/dist/{command-Df7u5eAT.cjs → command-BK93nizl.cjs} +6 -6
  8. package/dist/{command-ComOeFLY.mjs → command-nOI80Mnm.mjs} +6 -6
  9. package/dist/{index-CzvgPwr1.mjs → index-DnsqY6I_.mjs} +189 -60
  10. package/dist/{index-Cuvfa15L.cjs → index-J7QKJ8lc.cjs} +194 -61
  11. package/dist/index.cjs +8 -8
  12. package/dist/index.mjs +8 -8
  13. package/dist/lib.cjs +2 -3
  14. package/dist/lib.d.cts +2 -0
  15. package/dist/lib.d.mts +2 -0
  16. package/dist/lib.mjs +2 -3
  17. package/dist/{persistence-BxP6Jw1f.mjs → persistence-BMa6cyw9.mjs} +2 -3
  18. package/dist/{persistence-D7JtnrYA.cjs → persistence-xK5CKhbn.cjs} +2 -3
  19. package/dist/registerKillSessionHandler-CH6yN0eG.cjs +1198 -0
  20. package/dist/registerKillSessionHandler-Dxwg4L4J.mjs +1179 -0
  21. package/dist/{runClaude-C1W_Nw0C.cjs → runClaude-BMHlBny_.cjs} +884 -398
  22. package/dist/{runClaude-B_fTMxc4.mjs → runClaude-cQ-UT0Ke.mjs} +882 -396
  23. package/dist/{runCodex-CUgOiIEz.mjs → runCodex-AnJUPIhX.mjs} +155 -578
  24. package/dist/{runCodex-D2VCWVEK.cjs → runCodex-roOSOWWL.cjs} +158 -583
  25. package/dist/{runGemini-2_FEtJYa.mjs → runGemini-BGo_0mzA.mjs} +142 -387
  26. package/dist/{runGemini-CiGnjflq.cjs → runGemini-Cg6Zbqlz.cjs} +145 -390
  27. package/package.json +9 -8
  28. package/scripts/e2e/fake-codex-acp-agent.mjs +139 -0
  29. package/scripts/e2e/local-server-session-roundtrip.mjs +1063 -0
  30. package/scripts/release-smoke.mjs +23 -6
  31. package/dist/names-CicSgRNg.mjs +0 -625
  32. package/dist/names-yJNZoTv_.cjs +0 -636
  33. package/dist/registerKillSessionHandler-ARQrPvnT.mjs +0 -454
  34. package/dist/registerKillSessionHandler-DCMFiXyA.cjs +0 -459
@@ -9,21 +9,20 @@ import { io } from 'socket.io-client';
9
9
  import { z } from 'zod';
10
10
  import { randomBytes, createCipheriv, createDecipheriv, randomUUID, createHash as createHash$1, createHmac, hkdfSync } from 'node:crypto';
11
11
  import tweetnacl from 'tweetnacl';
12
- import { exec } from 'child_process';
13
- import { promisify } from 'util';
14
12
  import { readFile, stat, writeFile, readdir } from 'fs/promises';
15
13
  import { createHash } from 'crypto';
16
14
  import { resolve, join as join$1 } from 'path';
15
+ import { spawn } from 'node:child_process';
17
16
  import { Expo } from 'expo-server-sdk';
18
17
 
19
18
  var name = "happy-imou-cloud";
20
- var version = "2.0.10";
19
+ var version = "2.0.11";
21
20
  var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
22
21
  var author = "long.zhu";
23
22
  var license = "MIT";
24
23
  var type = "module";
25
24
  var bin = {
26
- hicloud: "./bin/happy-cloud.mjs"
25
+ hicloud: "bin/happy-cloud.mjs"
27
26
  };
28
27
  var main = "./dist/index.cjs";
29
28
  var module$1 = "./dist/index.mjs";
@@ -75,6 +74,7 @@ var scripts = {
75
74
  dev: "tsx src/index.ts",
76
75
  "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
77
76
  "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
77
+ "e2e:local-server": "yarn build && node ./scripts/e2e/local-server-session-roundtrip.mjs",
78
78
  "// ==== Release ====": "",
79
79
  prepublishOnly: "yarn release:smoke",
80
80
  release: "yarn install && release-it",
@@ -430,7 +430,7 @@ async function listDaemonLogFiles(limit = 50) {
430
430
  return { file, path: fullPath, modified: stats.mtime };
431
431
  }).sort((a, b) => b.modified.getTime() - a.modified.getTime());
432
432
  try {
433
- const { readDaemonState } = await import('./persistence-BxP6Jw1f.mjs');
433
+ const { readDaemonState } = await import('./persistence-BMa6cyw9.mjs');
434
434
  const state = await readDaemonState();
435
435
  if (!state) {
436
436
  return logs;
@@ -865,7 +865,131 @@ function validatePath(targetPath, workingDirectory) {
865
865
  return { valid: true };
866
866
  }
867
867
 
868
- const execAsync = promisify(exec);
868
+ const DEFAULT_SHELL_COMMAND_TIMEOUT_MS = 3e4;
869
+ const DEFAULT_SHELL_OUTPUT_MAX_BYTES = 256 * 1024;
870
+ class BoundedTailBuffer {
871
+ chunks = [];
872
+ maxBytes;
873
+ storedBytes = 0;
874
+ receivedBytes = 0;
875
+ constructor(maxBytes) {
876
+ this.maxBytes = Math.max(1, maxBytes);
877
+ }
878
+ append(chunk) {
879
+ const normalized = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
880
+ if (normalized.length === 0) {
881
+ return;
882
+ }
883
+ this.receivedBytes += normalized.length;
884
+ this.chunks.push(normalized);
885
+ this.storedBytes += normalized.length;
886
+ while (this.storedBytes > this.maxBytes && this.chunks.length > 0) {
887
+ const overflow = this.storedBytes - this.maxBytes;
888
+ const oldest = this.chunks[0];
889
+ if (oldest.length <= overflow) {
890
+ this.chunks.shift();
891
+ this.storedBytes -= oldest.length;
892
+ continue;
893
+ }
894
+ this.chunks[0] = oldest.subarray(overflow);
895
+ this.storedBytes -= overflow;
896
+ }
897
+ }
898
+ toString(label) {
899
+ const content = Buffer.concat(this.chunks).toString("utf8");
900
+ if (this.receivedBytes <= this.maxBytes) {
901
+ return content;
902
+ }
903
+ return `...[${label} truncated, showing last ${this.maxBytes} bytes of ${this.receivedBytes}]
904
+ ${content}`;
905
+ }
906
+ }
907
+ async function runShellCommand(opts) {
908
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SHELL_COMMAND_TIMEOUT_MS;
909
+ const maxOutputBytes = opts.maxOutputBytes ?? DEFAULT_SHELL_OUTPUT_MAX_BYTES;
910
+ return await new Promise((resolve) => {
911
+ const stdout = new BoundedTailBuffer(maxOutputBytes);
912
+ const stderr = new BoundedTailBuffer(maxOutputBytes);
913
+ const child = spawn(opts.command, [], {
914
+ cwd: opts.cwd,
915
+ shell: true,
916
+ windowsHide: true
917
+ });
918
+ let settled = false;
919
+ let timedOut = false;
920
+ let timeoutHandle;
921
+ const finish = (result) => {
922
+ if (settled) {
923
+ return;
924
+ }
925
+ settled = true;
926
+ if (timeoutHandle) {
927
+ clearTimeout(timeoutHandle);
928
+ }
929
+ resolve(result);
930
+ };
931
+ child.stdout?.on("data", (chunk) => {
932
+ stdout.append(chunk);
933
+ });
934
+ child.stderr?.on("data", (chunk) => {
935
+ stderr.append(chunk);
936
+ });
937
+ child.on("error", (error) => {
938
+ finish({
939
+ success: false,
940
+ stdout: stdout.toString("stdout"),
941
+ stderr: stderr.toString("stderr"),
942
+ exitCode: 1,
943
+ error: error.message
944
+ });
945
+ });
946
+ child.on("close", (code, signal) => {
947
+ const stdoutText = stdout.toString("stdout");
948
+ const stderrText = stderr.toString("stderr");
949
+ if (timedOut) {
950
+ finish({
951
+ success: false,
952
+ stdout: stdoutText,
953
+ stderr: stderrText,
954
+ exitCode: typeof code === "number" ? code : -1,
955
+ error: "Command timed out"
956
+ });
957
+ return;
958
+ }
959
+ if (code === 0) {
960
+ finish({
961
+ success: true,
962
+ stdout: stdoutText,
963
+ stderr: stderrText,
964
+ exitCode: 0
965
+ });
966
+ return;
967
+ }
968
+ finish({
969
+ success: false,
970
+ stdout: stdoutText,
971
+ stderr: stderrText,
972
+ exitCode: typeof code === "number" ? code : 1,
973
+ error: stderrText || (signal ? `Command exited due to signal ${signal}` : `Command failed with exit code ${code ?? "unknown"}`)
974
+ });
975
+ });
976
+ timeoutHandle = setTimeout(() => {
977
+ timedOut = true;
978
+ try {
979
+ child.kill();
980
+ } catch {
981
+ finish({
982
+ success: false,
983
+ stdout: stdout.toString("stdout"),
984
+ stderr: stderr.toString("stderr"),
985
+ exitCode: -1,
986
+ error: "Command timed out"
987
+ });
988
+ }
989
+ }, timeoutMs);
990
+ });
991
+ }
992
+
869
993
  function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
870
994
  rpcHandlerManager.registerHandler("bash", async (data) => {
871
995
  logger.debug("Shell command request:", data.command);
@@ -876,57 +1000,37 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
876
1000
  }
877
1001
  }
878
1002
  try {
879
- const options = {
880
- cwd: data.cwd === "/" ? void 0 : data.cwd,
1003
+ const cwd = data.cwd === "/" ? void 0 : data.cwd;
1004
+ logger.debug("Shell command executing...", {
1005
+ cwd,
881
1006
  timeout: data.timeout || 3e4
882
- // Default 30 seconds timeout
883
- };
884
- logger.debug("Shell command executing...", { cwd: options.cwd, timeout: options.timeout });
885
- const { stdout, stderr } = await execAsync(data.command, options);
886
- logger.debug("Shell command executed, processing result...");
887
- const result = {
888
- success: true,
889
- stdout: stdout ? stdout.toString() : "",
890
- stderr: stderr ? stderr.toString() : "",
891
- exitCode: 0
892
- };
893
- logger.debug("Shell command result:", {
894
- success: true,
895
- exitCode: 0,
1007
+ });
1008
+ const result = await runShellCommand({
1009
+ command: data.command,
1010
+ cwd,
1011
+ timeoutMs: data.timeout || 3e4
1012
+ });
1013
+ logger.debug("Shell command finished:", {
1014
+ success: result.success,
1015
+ exitCode: result.exitCode,
1016
+ error: result.error,
896
1017
  stdoutLen: result.stdout.length,
897
1018
  stderrLen: result.stderr.length
898
1019
  });
899
1020
  return result;
900
1021
  } catch (error) {
901
- const execError = error;
902
- if (execError.code === "ETIMEDOUT" || execError.killed) {
903
- const result2 = {
904
- success: false,
905
- stdout: execError.stdout || "",
906
- stderr: execError.stderr || "",
907
- exitCode: typeof execError.code === "number" ? execError.code : -1,
908
- error: "Command timed out"
909
- };
910
- logger.debug("Shell command timed out:", {
911
- success: false,
912
- exitCode: result2.exitCode,
913
- error: "Command timed out"
914
- });
915
- return result2;
916
- }
917
1022
  const result = {
918
1023
  success: false,
919
- stdout: execError.stdout ? execError.stdout.toString() : "",
920
- stderr: execError.stderr ? execError.stderr.toString() : execError.message || "Command failed",
921
- exitCode: typeof execError.code === "number" ? execError.code : 1,
922
- error: execError.message || "Command failed"
1024
+ stdout: "",
1025
+ stderr: "",
1026
+ exitCode: 1,
1027
+ error: error instanceof Error ? error.message : "Command failed"
923
1028
  };
924
- logger.debug("Shell command failed:", {
1029
+ logger.debug("Shell command failed before execution completed:", {
1030
+ cwd: data.cwd === "/" ? void 0 : data.cwd,
925
1031
  success: false,
926
1032
  exitCode: result.exitCode,
927
- error: result.error,
928
- stdoutLen: result.stdout.length,
929
- stderrLen: result.stderr.length
1033
+ error: result.error
930
1034
  });
931
1035
  return result;
932
1036
  }
@@ -1343,6 +1447,8 @@ function buildSocketAuth(opts) {
1343
1447
  return auth;
1344
1448
  }
1345
1449
 
1450
+ const MAX_PENDING_RELIABLE_CODEX_MESSAGES = 200;
1451
+ const MAX_PENDING_RELIABLE_CODEX_MESSAGE_BYTES = 512 * 1024;
1346
1452
  class ApiSessionClient extends EventEmitter {
1347
1453
  credentials;
1348
1454
  sessionId;
@@ -1359,6 +1465,7 @@ class ApiSessionClient extends EventEmitter {
1359
1465
  encryptionKey;
1360
1466
  encryptionVariant;
1361
1467
  pendingReliableCodexMessages = [];
1468
+ pendingReliableCodexMessageBytes = 0;
1362
1469
  reconnectAfterServerDisconnectTimer = null;
1363
1470
  lastSocketServerError = null;
1364
1471
  constructor(credentials, session) {
@@ -1565,6 +1672,8 @@ class ApiSessionClient extends EventEmitter {
1565
1672
  if (this.shouldBufferReliableCodexMessage(body)) {
1566
1673
  logger.debug("[API] Socket not connected, buffering reliable Codex message:", { type: eventType });
1567
1674
  this.pendingReliableCodexMessages.push({ encrypted, type: eventType });
1675
+ this.pendingReliableCodexMessageBytes += encrypted.length;
1676
+ this.trimPendingReliableCodexMessages();
1568
1677
  } else {
1569
1678
  logger.debug("[API] Socket not connected, dropping non-critical Codex message:", { type: eventType });
1570
1679
  }
@@ -1740,6 +1849,7 @@ class ApiSessionClient extends EventEmitter {
1740
1849
  return;
1741
1850
  }
1742
1851
  const buffered = this.pendingReliableCodexMessages.splice(0, this.pendingReliableCodexMessages.length);
1852
+ this.pendingReliableCodexMessageBytes = 0;
1743
1853
  logger.debug("[API] Flushing buffered Codex messages after reconnect", {
1744
1854
  count: buffered.length,
1745
1855
  types: buffered.map((message) => message.type)
@@ -1763,6 +1873,24 @@ class ApiSessionClient extends EventEmitter {
1763
1873
  return false;
1764
1874
  }
1765
1875
  }
1876
+ trimPendingReliableCodexMessages() {
1877
+ let dropped = 0;
1878
+ while (this.pendingReliableCodexMessages.length > MAX_PENDING_RELIABLE_CODEX_MESSAGES || this.pendingReliableCodexMessageBytes > MAX_PENDING_RELIABLE_CODEX_MESSAGE_BYTES) {
1879
+ const removed = this.pendingReliableCodexMessages.shift();
1880
+ if (!removed) {
1881
+ break;
1882
+ }
1883
+ this.pendingReliableCodexMessageBytes -= removed.encrypted.length;
1884
+ dropped += 1;
1885
+ }
1886
+ if (dropped > 0) {
1887
+ logger.debug("[API] Dropped oldest buffered Codex messages to cap reconnect memory usage", {
1888
+ dropped,
1889
+ remaining: this.pendingReliableCodexMessages.length,
1890
+ bytes: this.pendingReliableCodexMessageBytes
1891
+ });
1892
+ }
1893
+ }
1766
1894
  retryAfterServerDisconnect(reason) {
1767
1895
  if (reason !== "io server disconnect") {
1768
1896
  return;
@@ -11,21 +11,20 @@ var socket_ioClient = require('socket.io-client');
11
11
  var z = require('zod');
12
12
  var node_crypto = require('node:crypto');
13
13
  var tweetnacl = require('tweetnacl');
14
- var child_process = require('child_process');
15
- var util = require('util');
16
14
  var fs$2 = require('fs/promises');
17
15
  var crypto = require('crypto');
18
16
  var path$1 = require('path');
17
+ var node_child_process = require('node:child_process');
19
18
  var expoServerSdk = require('expo-server-sdk');
20
19
 
21
20
  var name = "happy-imou-cloud";
22
- var version = "2.0.10";
21
+ var version = "2.0.11";
23
22
  var description = "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI";
24
23
  var author = "long.zhu";
25
24
  var license = "MIT";
26
25
  var type = "module";
27
26
  var bin = {
28
- hicloud: "./bin/happy-cloud.mjs"
27
+ hicloud: "bin/happy-cloud.mjs"
29
28
  };
30
29
  var main = "./dist/index.cjs";
31
30
  var module$1 = "./dist/index.mjs";
@@ -77,6 +76,7 @@ var scripts = {
77
76
  dev: "tsx src/index.ts",
78
77
  "dev:local-server": "yarn build && tsx --env-file .env.dev-local-server src/index.ts",
79
78
  "dev:integration-test-env": "yarn build && tsx --env-file .env.integration-test src/index.ts",
79
+ "e2e:local-server": "yarn build && node ./scripts/e2e/local-server-session-roundtrip.mjs",
80
80
  "// ==== Release ====": "",
81
81
  prepublishOnly: "yarn release:smoke",
82
82
  release: "yarn install && release-it",
@@ -432,7 +432,7 @@ async function listDaemonLogFiles(limit = 50) {
432
432
  return { file, path: fullPath, modified: stats.mtime };
433
433
  }).sort((a, b) => b.modified.getTime() - a.modified.getTime());
434
434
  try {
435
- const { readDaemonState } = await Promise.resolve().then(function () { return require('./persistence-D7JtnrYA.cjs'); });
435
+ const { readDaemonState } = await Promise.resolve().then(function () { return require('./persistence-xK5CKhbn.cjs'); });
436
436
  const state = await readDaemonState();
437
437
  if (!state) {
438
438
  return logs;
@@ -867,7 +867,131 @@ function validatePath(targetPath, workingDirectory) {
867
867
  return { valid: true };
868
868
  }
869
869
 
870
- const execAsync = util.promisify(child_process.exec);
870
+ const DEFAULT_SHELL_COMMAND_TIMEOUT_MS = 3e4;
871
+ const DEFAULT_SHELL_OUTPUT_MAX_BYTES = 256 * 1024;
872
+ class BoundedTailBuffer {
873
+ chunks = [];
874
+ maxBytes;
875
+ storedBytes = 0;
876
+ receivedBytes = 0;
877
+ constructor(maxBytes) {
878
+ this.maxBytes = Math.max(1, maxBytes);
879
+ }
880
+ append(chunk) {
881
+ const normalized = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
882
+ if (normalized.length === 0) {
883
+ return;
884
+ }
885
+ this.receivedBytes += normalized.length;
886
+ this.chunks.push(normalized);
887
+ this.storedBytes += normalized.length;
888
+ while (this.storedBytes > this.maxBytes && this.chunks.length > 0) {
889
+ const overflow = this.storedBytes - this.maxBytes;
890
+ const oldest = this.chunks[0];
891
+ if (oldest.length <= overflow) {
892
+ this.chunks.shift();
893
+ this.storedBytes -= oldest.length;
894
+ continue;
895
+ }
896
+ this.chunks[0] = oldest.subarray(overflow);
897
+ this.storedBytes -= overflow;
898
+ }
899
+ }
900
+ toString(label) {
901
+ const content = Buffer.concat(this.chunks).toString("utf8");
902
+ if (this.receivedBytes <= this.maxBytes) {
903
+ return content;
904
+ }
905
+ return `...[${label} truncated, showing last ${this.maxBytes} bytes of ${this.receivedBytes}]
906
+ ${content}`;
907
+ }
908
+ }
909
+ async function runShellCommand(opts) {
910
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SHELL_COMMAND_TIMEOUT_MS;
911
+ const maxOutputBytes = opts.maxOutputBytes ?? DEFAULT_SHELL_OUTPUT_MAX_BYTES;
912
+ return await new Promise((resolve) => {
913
+ const stdout = new BoundedTailBuffer(maxOutputBytes);
914
+ const stderr = new BoundedTailBuffer(maxOutputBytes);
915
+ const child = node_child_process.spawn(opts.command, [], {
916
+ cwd: opts.cwd,
917
+ shell: true,
918
+ windowsHide: true
919
+ });
920
+ let settled = false;
921
+ let timedOut = false;
922
+ let timeoutHandle;
923
+ const finish = (result) => {
924
+ if (settled) {
925
+ return;
926
+ }
927
+ settled = true;
928
+ if (timeoutHandle) {
929
+ clearTimeout(timeoutHandle);
930
+ }
931
+ resolve(result);
932
+ };
933
+ child.stdout?.on("data", (chunk) => {
934
+ stdout.append(chunk);
935
+ });
936
+ child.stderr?.on("data", (chunk) => {
937
+ stderr.append(chunk);
938
+ });
939
+ child.on("error", (error) => {
940
+ finish({
941
+ success: false,
942
+ stdout: stdout.toString("stdout"),
943
+ stderr: stderr.toString("stderr"),
944
+ exitCode: 1,
945
+ error: error.message
946
+ });
947
+ });
948
+ child.on("close", (code, signal) => {
949
+ const stdoutText = stdout.toString("stdout");
950
+ const stderrText = stderr.toString("stderr");
951
+ if (timedOut) {
952
+ finish({
953
+ success: false,
954
+ stdout: stdoutText,
955
+ stderr: stderrText,
956
+ exitCode: typeof code === "number" ? code : -1,
957
+ error: "Command timed out"
958
+ });
959
+ return;
960
+ }
961
+ if (code === 0) {
962
+ finish({
963
+ success: true,
964
+ stdout: stdoutText,
965
+ stderr: stderrText,
966
+ exitCode: 0
967
+ });
968
+ return;
969
+ }
970
+ finish({
971
+ success: false,
972
+ stdout: stdoutText,
973
+ stderr: stderrText,
974
+ exitCode: typeof code === "number" ? code : 1,
975
+ error: stderrText || (signal ? `Command exited due to signal ${signal}` : `Command failed with exit code ${code ?? "unknown"}`)
976
+ });
977
+ });
978
+ timeoutHandle = setTimeout(() => {
979
+ timedOut = true;
980
+ try {
981
+ child.kill();
982
+ } catch {
983
+ finish({
984
+ success: false,
985
+ stdout: stdout.toString("stdout"),
986
+ stderr: stderr.toString("stderr"),
987
+ exitCode: -1,
988
+ error: "Command timed out"
989
+ });
990
+ }
991
+ }, timeoutMs);
992
+ });
993
+ }
994
+
871
995
  function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
872
996
  rpcHandlerManager.registerHandler("bash", async (data) => {
873
997
  logger.debug("Shell command request:", data.command);
@@ -878,57 +1002,37 @@ function registerCommonHandlers(rpcHandlerManager, workingDirectory) {
878
1002
  }
879
1003
  }
880
1004
  try {
881
- const options = {
882
- cwd: data.cwd === "/" ? void 0 : data.cwd,
1005
+ const cwd = data.cwd === "/" ? void 0 : data.cwd;
1006
+ logger.debug("Shell command executing...", {
1007
+ cwd,
883
1008
  timeout: data.timeout || 3e4
884
- // Default 30 seconds timeout
885
- };
886
- logger.debug("Shell command executing...", { cwd: options.cwd, timeout: options.timeout });
887
- const { stdout, stderr } = await execAsync(data.command, options);
888
- logger.debug("Shell command executed, processing result...");
889
- const result = {
890
- success: true,
891
- stdout: stdout ? stdout.toString() : "",
892
- stderr: stderr ? stderr.toString() : "",
893
- exitCode: 0
894
- };
895
- logger.debug("Shell command result:", {
896
- success: true,
897
- exitCode: 0,
1009
+ });
1010
+ const result = await runShellCommand({
1011
+ command: data.command,
1012
+ cwd,
1013
+ timeoutMs: data.timeout || 3e4
1014
+ });
1015
+ logger.debug("Shell command finished:", {
1016
+ success: result.success,
1017
+ exitCode: result.exitCode,
1018
+ error: result.error,
898
1019
  stdoutLen: result.stdout.length,
899
1020
  stderrLen: result.stderr.length
900
1021
  });
901
1022
  return result;
902
1023
  } catch (error) {
903
- const execError = error;
904
- if (execError.code === "ETIMEDOUT" || execError.killed) {
905
- const result2 = {
906
- success: false,
907
- stdout: execError.stdout || "",
908
- stderr: execError.stderr || "",
909
- exitCode: typeof execError.code === "number" ? execError.code : -1,
910
- error: "Command timed out"
911
- };
912
- logger.debug("Shell command timed out:", {
913
- success: false,
914
- exitCode: result2.exitCode,
915
- error: "Command timed out"
916
- });
917
- return result2;
918
- }
919
1024
  const result = {
920
1025
  success: false,
921
- stdout: execError.stdout ? execError.stdout.toString() : "",
922
- stderr: execError.stderr ? execError.stderr.toString() : execError.message || "Command failed",
923
- exitCode: typeof execError.code === "number" ? execError.code : 1,
924
- error: execError.message || "Command failed"
1026
+ stdout: "",
1027
+ stderr: "",
1028
+ exitCode: 1,
1029
+ error: error instanceof Error ? error.message : "Command failed"
925
1030
  };
926
- logger.debug("Shell command failed:", {
1031
+ logger.debug("Shell command failed before execution completed:", {
1032
+ cwd: data.cwd === "/" ? void 0 : data.cwd,
927
1033
  success: false,
928
1034
  exitCode: result.exitCode,
929
- error: result.error,
930
- stdoutLen: result.stdout.length,
931
- stderrLen: result.stderr.length
1035
+ error: result.error
932
1036
  });
933
1037
  return result;
934
1038
  }
@@ -1345,6 +1449,8 @@ function buildSocketAuth(opts) {
1345
1449
  return auth;
1346
1450
  }
1347
1451
 
1452
+ const MAX_PENDING_RELIABLE_CODEX_MESSAGES = 200;
1453
+ const MAX_PENDING_RELIABLE_CODEX_MESSAGE_BYTES = 512 * 1024;
1348
1454
  class ApiSessionClient extends node_events.EventEmitter {
1349
1455
  credentials;
1350
1456
  sessionId;
@@ -1361,6 +1467,7 @@ class ApiSessionClient extends node_events.EventEmitter {
1361
1467
  encryptionKey;
1362
1468
  encryptionVariant;
1363
1469
  pendingReliableCodexMessages = [];
1470
+ pendingReliableCodexMessageBytes = 0;
1364
1471
  reconnectAfterServerDisconnectTimer = null;
1365
1472
  lastSocketServerError = null;
1366
1473
  constructor(credentials, session) {
@@ -1567,6 +1674,8 @@ class ApiSessionClient extends node_events.EventEmitter {
1567
1674
  if (this.shouldBufferReliableCodexMessage(body)) {
1568
1675
  logger.debug("[API] Socket not connected, buffering reliable Codex message:", { type: eventType });
1569
1676
  this.pendingReliableCodexMessages.push({ encrypted, type: eventType });
1677
+ this.pendingReliableCodexMessageBytes += encrypted.length;
1678
+ this.trimPendingReliableCodexMessages();
1570
1679
  } else {
1571
1680
  logger.debug("[API] Socket not connected, dropping non-critical Codex message:", { type: eventType });
1572
1681
  }
@@ -1742,6 +1851,7 @@ class ApiSessionClient extends node_events.EventEmitter {
1742
1851
  return;
1743
1852
  }
1744
1853
  const buffered = this.pendingReliableCodexMessages.splice(0, this.pendingReliableCodexMessages.length);
1854
+ this.pendingReliableCodexMessageBytes = 0;
1745
1855
  logger.debug("[API] Flushing buffered Codex messages after reconnect", {
1746
1856
  count: buffered.length,
1747
1857
  types: buffered.map((message) => message.type)
@@ -1765,6 +1875,24 @@ class ApiSessionClient extends node_events.EventEmitter {
1765
1875
  return false;
1766
1876
  }
1767
1877
  }
1878
+ trimPendingReliableCodexMessages() {
1879
+ let dropped = 0;
1880
+ while (this.pendingReliableCodexMessages.length > MAX_PENDING_RELIABLE_CODEX_MESSAGES || this.pendingReliableCodexMessageBytes > MAX_PENDING_RELIABLE_CODEX_MESSAGE_BYTES) {
1881
+ const removed = this.pendingReliableCodexMessages.shift();
1882
+ if (!removed) {
1883
+ break;
1884
+ }
1885
+ this.pendingReliableCodexMessageBytes -= removed.encrypted.length;
1886
+ dropped += 1;
1887
+ }
1888
+ if (dropped > 0) {
1889
+ logger.debug("[API] Dropped oldest buffered Codex messages to cap reconnect memory usage", {
1890
+ dropped,
1891
+ remaining: this.pendingReliableCodexMessages.length,
1892
+ bytes: this.pendingReliableCodexMessageBytes
1893
+ });
1894
+ }
1895
+ }
1768
1896
  retryAfterServerDisconnect(reason) {
1769
1897
  if (reason !== "io server disconnect") {
1770
1898
  return;
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-Cuvfa15L.cjs');
3
+ var index = require('./index-J7QKJ8lc.cjs');
4
4
  require('chalk');
5
- require('./api-DUE5TJBE.cjs');
5
+ require('./api-Ye-rPX6s.cjs');
6
6
  require('axios');
7
7
  require('fs');
8
8
  require('node:fs');
@@ -13,13 +13,12 @@ require('socket.io-client');
13
13
  require('zod');
14
14
  require('node:crypto');
15
15
  require('tweetnacl');
16
- require('child_process');
17
- require('util');
18
16
  require('fs/promises');
19
17
  require('crypto');
20
18
  require('path');
19
+ require('node:child_process');
21
20
  require('expo-server-sdk');
22
- require('./persistence-D7JtnrYA.cjs');
21
+ require('./persistence-xK5CKhbn.cjs');
23
22
  require('node:fs/promises');
24
23
  require('os');
25
24
  require('tmp');
@@ -28,14 +27,15 @@ require('node:module');
28
27
  require('open');
29
28
  require('react');
30
29
  require('ink');
30
+ require('child_process');
31
31
  require('url');
32
- require('node:child_process');
33
32
  require('ps-list');
34
33
  require('cross-spawn');
35
34
  require('fastify');
36
35
  require('fastify-type-provider-zod');
37
36
  require('node:readline');
38
37
  require('http');
38
+ require('util');
39
39
  require('@agentclientprotocol/sdk');
40
40
 
41
41
  function listRuntimeProviders() {