happy-imou-cloud 2.1.7 → 2.1.8

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 (32) hide show
  1. package/bin/happy-cloud.mjs +1 -1
  2. package/dist/{BaseReasoningProcessor-iSuaFeZH.cjs → BaseReasoningProcessor-CbqNgi4p.cjs} +2 -2
  3. package/dist/{BaseReasoningProcessor-C0A6Jr8V.mjs → BaseReasoningProcessor-DJ9zxAdt.mjs} +2 -2
  4. package/dist/{ProviderSelectionHandler-DI9QK1iY.cjs → ProviderSelectionHandler-BZVtGMAn.cjs} +2 -2
  5. package/dist/{ProviderSelectionHandler-WT-tvePy.mjs → ProviderSelectionHandler-BleheBks.mjs} +2 -2
  6. package/dist/{api-CdGT5hsH.cjs → api-CeIpGPqs.cjs} +86 -32
  7. package/dist/{api-BYKV7vX6.mjs → api-DRdn4-dL.mjs} +86 -32
  8. package/dist/{command-uyA8cYmL.cjs → command-CTad-7bA.cjs} +3 -3
  9. package/dist/{command-C1cKqmsa.mjs → command-mDMWVdh5.mjs} +3 -3
  10. package/dist/{index-BAhlFq45.mjs → index-C4S85XB7.mjs} +144 -29
  11. package/dist/{index-D_S_7bqK.cjs → index-D68EOBHW.cjs} +147 -32
  12. package/dist/index.cjs +3 -3
  13. package/dist/index.mjs +3 -3
  14. package/dist/lib.cjs +1 -1
  15. package/dist/lib.d.cts +7 -4
  16. package/dist/lib.d.mts +7 -4
  17. package/dist/lib.mjs +1 -1
  18. package/dist/{persistence-CMvrZ4SA.cjs → persistence-Czyd-Uei.cjs} +1 -1
  19. package/dist/{persistence-B8Wgn6aN.mjs → persistence-DgpGouOO.mjs} +1 -1
  20. package/dist/{registerKillSessionHandler-DjxtkGMv.cjs → registerKillSessionHandler-DECzSYvQ.cjs} +3 -3
  21. package/dist/{registerKillSessionHandler-5DVlZaJx.mjs → registerKillSessionHandler-Dg0DFPae.mjs} +3 -3
  22. package/dist/{runClaude-DNZFsQY0.cjs → runClaude-DtCH-nx-.cjs} +9 -5
  23. package/dist/{runClaude-WB884iOO.mjs → runClaude-OWT6ZYiP.mjs} +9 -5
  24. package/dist/{runCodex-MJar-238.mjs → runCodex-BU3BA1l8.mjs} +96 -21
  25. package/dist/{runCodex-WZ91ZLK7.cjs → runCodex-reARLjN0.cjs} +96 -21
  26. package/dist/{runGemini-B_wCHgPU.cjs → runGemini-BvJUvOvj.cjs} +11 -5
  27. package/dist/{runGemini-BPGpwljp.mjs → runGemini-DeLxSapY.mjs} +11 -5
  28. package/package.json +1 -1
  29. package/scripts/devtools/README.md +9 -9
  30. package/scripts/e2e/fake-codex-acp-agent.mjs +139 -139
  31. package/scripts/e2e/local-server-session-roundtrip.mjs +1063 -1063
  32. package/scripts/ensureAcpSdkCompat.mjs +1 -1
package/dist/lib.d.cts CHANGED
@@ -2036,8 +2036,8 @@ declare class ApiSessionClient extends EventEmitter {
2036
2036
  private metadataLock;
2037
2037
  private encryptionKey;
2038
2038
  private encryptionVariant;
2039
- private pendingReliableCodexMessages;
2040
- private pendingReliableCodexMessageBytes;
2039
+ private pendingReliableSessionMessages;
2040
+ private pendingReliableSessionMessageBytes;
2041
2041
  private reconnectAfterServerDisconnectTimer;
2042
2042
  private lastSocketServerError;
2043
2043
  private protocolV3SessionSync;
@@ -2125,9 +2125,12 @@ declare class ApiSessionClient extends EventEmitter {
2125
2125
  private bufferLiveSessionEvent;
2126
2126
  private supportsKnownProtocolCapability;
2127
2127
  private emitEncryptedSessionMessage;
2128
- private flushReliableCodexMessages;
2128
+ private bufferReliableSessionMessage;
2129
+ private flushReliableSessionMessages;
2129
2130
  private shouldBufferReliableCodexMessage;
2130
- private trimPendingReliableCodexMessages;
2131
+ private shouldBufferReliableAcpMessage;
2132
+ private shouldBufferReliableSessionEvent;
2133
+ private trimPendingReliableSessionMessages;
2131
2134
  private retryAfterServerDisconnect;
2132
2135
  private clearReconnectAfterServerDisconnectTimer;
2133
2136
  private normalizeSocketError;
package/dist/lib.d.mts CHANGED
@@ -2036,8 +2036,8 @@ declare class ApiSessionClient extends EventEmitter {
2036
2036
  private metadataLock;
2037
2037
  private encryptionKey;
2038
2038
  private encryptionVariant;
2039
- private pendingReliableCodexMessages;
2040
- private pendingReliableCodexMessageBytes;
2039
+ private pendingReliableSessionMessages;
2040
+ private pendingReliableSessionMessageBytes;
2041
2041
  private reconnectAfterServerDisconnectTimer;
2042
2042
  private lastSocketServerError;
2043
2043
  private protocolV3SessionSync;
@@ -2125,9 +2125,12 @@ declare class ApiSessionClient extends EventEmitter {
2125
2125
  private bufferLiveSessionEvent;
2126
2126
  private supportsKnownProtocolCapability;
2127
2127
  private emitEncryptedSessionMessage;
2128
- private flushReliableCodexMessages;
2128
+ private bufferReliableSessionMessage;
2129
+ private flushReliableSessionMessages;
2129
2130
  private shouldBufferReliableCodexMessage;
2130
- private trimPendingReliableCodexMessages;
2131
+ private shouldBufferReliableAcpMessage;
2132
+ private shouldBufferReliableSessionEvent;
2133
+ private trimPendingReliableSessionMessages;
2131
2134
  private retryAfterServerDisconnect;
2132
2135
  private clearReconnectAfterServerDisconnectTimer;
2133
2136
  private normalizeSocketError;
package/dist/lib.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export { A as ApiClient, a as ApiSessionClient, c as configuration, l as logger } from './api-BYKV7vX6.mjs';
1
+ export { A as ApiClient, a as ApiSessionClient, c as configuration, l as logger } from './api-DRdn4-dL.mjs';
2
2
  export { R as RawJSONLinesSchema } from './types-CiliQpqS.mjs';
3
3
  import 'axios';
4
4
  import 'chalk';
@@ -3,7 +3,7 @@
3
3
  var promises = require('node:fs/promises');
4
4
  var fs = require('node:fs');
5
5
  var path = require('node:path');
6
- var api = require('./api-CdGT5hsH.cjs');
6
+ var api = require('./api-CeIpGPqs.cjs');
7
7
  var z = require('zod');
8
8
  require('axios');
9
9
  require('chalk');
@@ -1,7 +1,7 @@
1
1
  import { unlink, readFile, mkdir, open, stat, writeFile, rename } from 'node:fs/promises';
2
2
  import { existsSync, unlinkSync, readdirSync, constants, writeFileSync, readFileSync } from 'node:fs';
3
3
  import { join, dirname } from 'node:path';
4
- import { c as configuration, l as logger, e as encodeBase64 } from './api-BYKV7vX6.mjs';
4
+ import { c as configuration, l as logger, e as encodeBase64 } from './api-DRdn4-dL.mjs';
5
5
  import * as z from 'zod';
6
6
  import 'axios';
7
7
  import 'chalk';
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-D_S_7bqK.cjs');
4
- var persistence = require('./persistence-CMvrZ4SA.cjs');
3
+ var index = require('./index-D68EOBHW.cjs');
4
+ var persistence = require('./persistence-Czyd-Uei.cjs');
5
5
  var node_crypto = require('node:crypto');
6
- var api = require('./api-CdGT5hsH.cjs');
6
+ var api = require('./api-CeIpGPqs.cjs');
7
7
  var crypto = require('crypto');
8
8
  require('axios');
9
9
  require('node:events');
@@ -1,7 +1,7 @@
1
- import { k as initialMachineMetadata, R as RuntimeShell, l as resolveCanonicalToolNameV2, f as formatDisplayMessage } from './index-BAhlFq45.mjs';
2
- import { readSettings } from './persistence-B8Wgn6aN.mjs';
1
+ import { k as initialMachineMetadata, R as RuntimeShell, l as resolveCanonicalToolNameV2, f as formatDisplayMessage } from './index-C4S85XB7.mjs';
2
+ import { readSettings } from './persistence-DgpGouOO.mjs';
3
3
  import { randomUUID } from 'node:crypto';
4
- import { H as HAPPY_ORG_TURN_REPORT_TAG, d as HAPPY_ORG_SUMMARY_MAX_LENGTH, f as HAPPY_ORG_REPEAT_THRESHOLD, l as logger } from './api-BYKV7vX6.mjs';
4
+ import { H as HAPPY_ORG_TURN_REPORT_TAG, d as HAPPY_ORG_SUMMARY_MAX_LENGTH, f as HAPPY_ORG_REPEAT_THRESHOLD, l as logger } from './api-DRdn4-dL.mjs';
5
5
  import { createHash } from 'crypto';
6
6
  import 'axios';
7
7
  import 'node:events';
@@ -1,10 +1,10 @@
1
1
  'use strict';
2
2
 
3
3
  var node_crypto = require('node:crypto');
4
- var api = require('./api-CdGT5hsH.cjs');
4
+ var api = require('./api-CeIpGPqs.cjs');
5
5
  require('cross-spawn');
6
6
  require('@agentclientprotocol/sdk');
7
- var index = require('./index-D_S_7bqK.cjs');
7
+ var index = require('./index-D68EOBHW.cjs');
8
8
  require('ps-list');
9
9
  require('fs');
10
10
  require('path');
@@ -15,7 +15,7 @@ var path = require('node:path');
15
15
  var os = require('node:os');
16
16
  var node_child_process = require('node:child_process');
17
17
  require('node:readline');
18
- require('./persistence-CMvrZ4SA.cjs');
18
+ require('./persistence-Czyd-Uei.cjs');
19
19
  var promises = require('node:fs/promises');
20
20
  var fs = require('fs/promises');
21
21
  require('crypto');
@@ -26,9 +26,9 @@ require('tweetnacl');
26
26
  require('open');
27
27
  var React = require('react');
28
28
  var ink = require('ink');
29
- var ProviderSelectionHandler = require('./ProviderSelectionHandler-DI9QK1iY.cjs');
29
+ var ProviderSelectionHandler = require('./ProviderSelectionHandler-BZVtGMAn.cjs');
30
30
  var types = require('./types-DVk3crez.cjs');
31
- var registerKillSessionHandler = require('./registerKillSessionHandler-DjxtkGMv.cjs');
31
+ var registerKillSessionHandler = require('./registerKillSessionHandler-DECzSYvQ.cjs');
32
32
  require('socket.io-client');
33
33
  require('expo-server-sdk');
34
34
  var node_util = require('node:util');
@@ -1386,6 +1386,10 @@ ${systemPrompt}` : systemPrompt,
1386
1386
  let message = pending;
1387
1387
  pending = null;
1388
1388
  if (!message) {
1389
+ if (!shouldExit && session.queue.size() === 0 && !readyAlreadySent) {
1390
+ sendReady();
1391
+ readyAlreadySent = true;
1392
+ }
1389
1393
  const waitSignal = abortController.signal;
1390
1394
  const batch = await session.queue.waitForMessagesAndGetAsString(waitSignal);
1391
1395
  if (!batch) {
@@ -1,8 +1,8 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { l as logger, g as backoff, h as delay, j as AsyncLock, c as configuration, s as startOfflineReconnection, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-BYKV7vX6.mjs';
2
+ import { l as logger, g as backoff, h as delay, j as AsyncLock, c as configuration, s as startOfflineReconnection, b as connectionState, A as ApiClient, i as isAuthenticationRequiredError } from './api-DRdn4-dL.mjs';
3
3
  import 'cross-spawn';
4
4
  import '@agentclientprotocol/sdk';
5
- import { m as getProjectPath, F as Future, n as claudeLocal, E as ExitCodeError, o as trimIdent, q as createClaudeBackend, f as formatDisplayMessage, t as truncateDisplayMessage, u as claudeCheckSession, w as projectPath, x as mapToClaudeMode, P as PushableAsyncIterable, y as query, A as AbortError, e as stopCaffeinate, p as publishSessionRegistration, z as getEnvironmentInfo, a as createSessionMetadata, B as startCaffeinate, b as closeProviderSession } from './index-BAhlFq45.mjs';
5
+ import { m as getProjectPath, F as Future, n as claudeLocal, E as ExitCodeError, o as trimIdent, q as createClaudeBackend, f as formatDisplayMessage, t as truncateDisplayMessage, u as claudeCheckSession, w as projectPath, x as mapToClaudeMode, P as PushableAsyncIterable, y as query, A as AbortError, e as stopCaffeinate, p as publishSessionRegistration, z as getEnvironmentInfo, a as createSessionMetadata, B as startCaffeinate, b as closeProviderSession } from './index-C4S85XB7.mjs';
6
6
  import 'ps-list';
7
7
  import 'fs';
8
8
  import 'path';
@@ -13,7 +13,7 @@ import { dirname, basename, join, resolve } from 'node:path';
13
13
  import { homedir } from 'node:os';
14
14
  import { execSync } from 'node:child_process';
15
15
  import 'node:readline';
16
- import './persistence-B8Wgn6aN.mjs';
16
+ import './persistence-DgpGouOO.mjs';
17
17
  import { readFile } from 'node:fs/promises';
18
18
  import { stat, watch, access } from 'fs/promises';
19
19
  import 'crypto';
@@ -24,9 +24,9 @@ import 'tweetnacl';
24
24
  import 'open';
25
25
  import React, { useState, useRef, useEffect, useCallback } from 'react';
26
26
  import { useStdout, useInput, Box, Text, render } from 'ink';
27
- import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-WT-tvePy.mjs';
27
+ import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-BleheBks.mjs';
28
28
  import { R as RawJSONLinesSchema } from './types-CiliQpqS.mjs';
29
- import { B as BasePermissionHandler, d as MessageBuffer, C as ConversationHistory$1, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurn, l as launchRuntimeHandleWithFactoryResult, k as forwardAgentMessageToProviderSession, s as syncControlledByUserState, r as resolveHappyOrgQueuedTurn, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, h as hashObject, c as registerKillSessionHandler } from './registerKillSessionHandler-5DVlZaJx.mjs';
29
+ import { B as BasePermissionHandler, d as MessageBuffer, C as ConversationHistory$1, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurn, l as launchRuntimeHandleWithFactoryResult, k as forwardAgentMessageToProviderSession, s as syncControlledByUserState, r as resolveHappyOrgQueuedTurn, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, h as hashObject, c as registerKillSessionHandler } from './registerKillSessionHandler-Dg0DFPae.mjs';
30
30
  import 'socket.io-client';
31
31
  import 'expo-server-sdk';
32
32
  import { isDeepStrictEqual } from 'node:util';
@@ -1384,6 +1384,10 @@ ${systemPrompt}` : systemPrompt,
1384
1384
  let message = pending;
1385
1385
  pending = null;
1386
1386
  if (!message) {
1387
+ if (!shouldExit && session.queue.size() === 0 && !readyAlreadySent) {
1388
+ sendReady();
1389
+ readyAlreadySent = true;
1390
+ }
1387
1391
  const waitSignal = abortController.signal;
1388
1392
  const batch = await session.queue.waitForMessagesAndGetAsString(waitSignal);
1389
1393
  if (!batch) {
@@ -1,6 +1,6 @@
1
- import { l as logger, b as connectionState, A as ApiClient } from './api-BYKV7vX6.mjs';
2
- import { B as BasePermissionHandler, h as hashObject, d as MessageBuffer, C as ConversationHistory$1, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurn, c as registerKillSessionHandler, l as launchRuntimeHandleWithFactoryResult, j as inferToolResultError, k as forwardAgentMessageToProviderSession, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, r as resolveHappyOrgQueuedTurn, s as syncControlledByUserState } from './registerKillSessionHandler-5DVlZaJx.mjs';
3
- import { f as formatDisplayMessage, v as validateCodexAcpSpawn, h as createCodexBackend, t as truncateDisplayMessage, b as closeProviderSession, e as stopCaffeinate, i as readManagedSessionTag, j as resolveManagedSessionTag } from './index-BAhlFq45.mjs';
1
+ import { l as logger, b as connectionState, A as ApiClient } from './api-DRdn4-dL.mjs';
2
+ import { B as BasePermissionHandler, h as hashObject, d as MessageBuffer, C as ConversationHistory$1, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurn, c as registerKillSessionHandler, l as launchRuntimeHandleWithFactoryResult, j as inferToolResultError, k as forwardAgentMessageToProviderSession, e as ensureManagedProviderMachine, M as MissingMachineIdError, b as MessageQueue2, r as resolveHappyOrgQueuedTurn, s as syncControlledByUserState } from './registerKillSessionHandler-Dg0DFPae.mjs';
3
+ import { f as formatDisplayMessage, v as validateCodexAcpSpawn, h as createCodexBackend, t as truncateDisplayMessage, b as closeProviderSession, e as stopCaffeinate, i as readManagedSessionTag, j as resolveManagedSessionTag } from './index-C4S85XB7.mjs';
4
4
  import 'cross-spawn';
5
5
  import '@agentclientprotocol/sdk';
6
6
  import { randomUUID } from 'node:crypto';
@@ -14,7 +14,7 @@ import 'node:path';
14
14
  import 'node:os';
15
15
  import 'node:child_process';
16
16
  import 'node:readline';
17
- import './persistence-B8Wgn6aN.mjs';
17
+ import './persistence-DgpGouOO.mjs';
18
18
  import 'node:fs/promises';
19
19
  import 'fs/promises';
20
20
  import 'crypto';
@@ -25,8 +25,8 @@ import 'tweetnacl';
25
25
  import 'open';
26
26
  import React, { useState, useRef, useEffect, useCallback } from 'react';
27
27
  import { useStdout, useInput, Box, Text, render } from 'ink';
28
- import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-WT-tvePy.mjs';
29
- import { B as BaseReasoningProcessor, b as bootstrapManagedProviderSession } from './BaseReasoningProcessor-C0A6Jr8V.mjs';
28
+ import { c as createKeepAliveController, P as ProviderSelectionHandler, r as runModeLoop } from './ProviderSelectionHandler-BleheBks.mjs';
29
+ import { B as BaseReasoningProcessor, b as bootstrapManagedProviderSession } from './BaseReasoningProcessor-DJ9zxAdt.mjs';
30
30
  import 'zod';
31
31
  import 'socket.io-client';
32
32
  import 'expo-server-sdk';
@@ -977,6 +977,10 @@ async function codexRemoteLauncher(session) {
977
977
  let message = pending;
978
978
  pending = null;
979
979
  if (!message) {
980
+ if (!shouldExit && session.queue.size() === 0 && !readyAlreadySent) {
981
+ sendReady();
982
+ readyAlreadySent = true;
983
+ }
980
984
  const waitSignal = abortController.signal;
981
985
  const batch = await session.queue.waitForMessagesAndGetAsString(waitSignal);
982
986
  if (!batch) {
@@ -1155,6 +1159,58 @@ async function codexLoop(opts) {
1155
1159
  });
1156
1160
  }
1157
1161
 
1162
+ function normalizeFatalProcessError(error) {
1163
+ if (error instanceof Error) {
1164
+ return error;
1165
+ }
1166
+ const message = typeof error === "string" ? error : (() => {
1167
+ try {
1168
+ const serialized = JSON.stringify(error);
1169
+ return serialized && serialized !== "{}" ? serialized : String(error);
1170
+ } catch {
1171
+ return String(error);
1172
+ }
1173
+ })();
1174
+ return new Error(message || "Unknown fatal process error");
1175
+ }
1176
+ function installFatalProcessHandlers(options) {
1177
+ const target = options.target ?? process;
1178
+ const exit = options.exit ?? process.exit;
1179
+ let shuttingDown = false;
1180
+ let disposed = false;
1181
+ const handleFatalEvent = async (event, reason) => {
1182
+ const error = normalizeFatalProcessError(reason);
1183
+ logger.debug(`[${options.label}] Fatal ${event}`, error);
1184
+ if (shuttingDown) {
1185
+ logger.debug(`[${options.label}] Ignoring duplicate fatal ${event} while shutdown is already in progress`);
1186
+ return;
1187
+ }
1188
+ shuttingDown = true;
1189
+ try {
1190
+ await options.cleanup({ event, error });
1191
+ } catch (cleanupError) {
1192
+ logger.debug(`[${options.label}] Fatal cleanup failed`, cleanupError);
1193
+ }
1194
+ exit(1);
1195
+ };
1196
+ const onUncaughtException = (error) => {
1197
+ void handleFatalEvent("uncaughtException", error);
1198
+ };
1199
+ const onUnhandledRejection = (reason) => {
1200
+ void handleFatalEvent("unhandledRejection", reason);
1201
+ };
1202
+ target.on("uncaughtException", onUncaughtException);
1203
+ target.on("unhandledRejection", onUnhandledRejection);
1204
+ return () => {
1205
+ if (disposed) {
1206
+ return;
1207
+ }
1208
+ disposed = true;
1209
+ target.off("uncaughtException", onUncaughtException);
1210
+ target.off("unhandledRejection", onUnhandledRejection);
1211
+ };
1212
+ }
1213
+
1158
1214
  function resolveInitialCodexPermissionMode(opts) {
1159
1215
  if (opts.permissionMode) {
1160
1216
  return opts.permissionMode;
@@ -1296,30 +1352,49 @@ async function runCodex(opts) {
1296
1352
  let loopError;
1297
1353
  let closeError;
1298
1354
  let observerCloseError;
1299
- try {
1300
- exitCode = await codexLoop({
1301
- session: codexSession,
1302
- startingMode: requestedStartingMode
1303
- });
1304
- logger.debug(`[codex] codexLoop resolved with exit code ${exitCode}`);
1305
- } catch (error) {
1306
- loopError = error;
1307
- } finally {
1355
+ let cleanupStarted = false;
1356
+ const cleanupResources = async (closeOptions = {
1357
+ archiveOnClose: true
1358
+ }) => {
1359
+ if (cleanupStarted) {
1360
+ return;
1361
+ }
1362
+ cleanupStarted = true;
1308
1363
  try {
1309
- await closeProviderSession(sessionClient, {
1310
- archiveOnClose: true
1311
- });
1364
+ await closeProviderSession(sessionClient, closeOptions);
1312
1365
  } catch (error) {
1313
- closeError = error;
1366
+ closeError = closeError ?? error;
1314
1367
  }
1315
1368
  try {
1316
1369
  await userScopedObserver?.close();
1317
1370
  } catch (error) {
1318
- observerCloseError = error;
1371
+ observerCloseError = observerCloseError ?? error;
1319
1372
  }
1320
1373
  stopCaffeinate();
1321
1374
  reconnectionHandle?.cancel();
1322
- codexSession.cleanup();
1375
+ codexSession?.cleanup();
1376
+ };
1377
+ const disposeFatalProcessHandlers = installFatalProcessHandlers({
1378
+ label: "codex",
1379
+ cleanup: async ({ event, error }) => {
1380
+ await cleanupResources({
1381
+ archiveReason: `Fatal ${event}: ${error.message}`
1382
+ });
1383
+ }
1384
+ });
1385
+ try {
1386
+ exitCode = await codexLoop({
1387
+ session: codexSession,
1388
+ startingMode: requestedStartingMode
1389
+ });
1390
+ logger.debug(`[codex] codexLoop resolved with exit code ${exitCode}`);
1391
+ } catch (error) {
1392
+ loopError = error;
1393
+ } finally {
1394
+ disposeFatalProcessHandlers();
1395
+ await cleanupResources({
1396
+ archiveOnClose: true
1397
+ });
1323
1398
  }
1324
1399
  if (loopError !== void 0) {
1325
1400
  logger.debug("[codex] runCodex exiting after loop error", loopError);
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
- var api = require('./api-CdGT5hsH.cjs');
4
- var registerKillSessionHandler = require('./registerKillSessionHandler-DjxtkGMv.cjs');
5
- var index = require('./index-D_S_7bqK.cjs');
3
+ var api = require('./api-CeIpGPqs.cjs');
4
+ var registerKillSessionHandler = require('./registerKillSessionHandler-DECzSYvQ.cjs');
5
+ var index = require('./index-D68EOBHW.cjs');
6
6
  require('cross-spawn');
7
7
  require('@agentclientprotocol/sdk');
8
8
  var node_crypto = require('node:crypto');
@@ -16,7 +16,7 @@ require('node:path');
16
16
  require('node:os');
17
17
  require('node:child_process');
18
18
  require('node:readline');
19
- require('./persistence-CMvrZ4SA.cjs');
19
+ require('./persistence-Czyd-Uei.cjs');
20
20
  require('node:fs/promises');
21
21
  require('fs/promises');
22
22
  require('crypto');
@@ -27,8 +27,8 @@ require('tweetnacl');
27
27
  require('open');
28
28
  var React = require('react');
29
29
  var ink = require('ink');
30
- var ProviderSelectionHandler = require('./ProviderSelectionHandler-DI9QK1iY.cjs');
31
- var BaseReasoningProcessor = require('./BaseReasoningProcessor-iSuaFeZH.cjs');
30
+ var ProviderSelectionHandler = require('./ProviderSelectionHandler-BZVtGMAn.cjs');
31
+ var BaseReasoningProcessor = require('./BaseReasoningProcessor-CbqNgi4p.cjs');
32
32
  require('zod');
33
33
  require('socket.io-client');
34
34
  require('expo-server-sdk');
@@ -979,6 +979,10 @@ async function codexRemoteLauncher(session) {
979
979
  let message = pending;
980
980
  pending = null;
981
981
  if (!message) {
982
+ if (!shouldExit && session.queue.size() === 0 && !readyAlreadySent) {
983
+ sendReady();
984
+ readyAlreadySent = true;
985
+ }
982
986
  const waitSignal = abortController.signal;
983
987
  const batch = await session.queue.waitForMessagesAndGetAsString(waitSignal);
984
988
  if (!batch) {
@@ -1157,6 +1161,58 @@ async function codexLoop(opts) {
1157
1161
  });
1158
1162
  }
1159
1163
 
1164
+ function normalizeFatalProcessError(error) {
1165
+ if (error instanceof Error) {
1166
+ return error;
1167
+ }
1168
+ const message = typeof error === "string" ? error : (() => {
1169
+ try {
1170
+ const serialized = JSON.stringify(error);
1171
+ return serialized && serialized !== "{}" ? serialized : String(error);
1172
+ } catch {
1173
+ return String(error);
1174
+ }
1175
+ })();
1176
+ return new Error(message || "Unknown fatal process error");
1177
+ }
1178
+ function installFatalProcessHandlers(options) {
1179
+ const target = options.target ?? process;
1180
+ const exit = options.exit ?? process.exit;
1181
+ let shuttingDown = false;
1182
+ let disposed = false;
1183
+ const handleFatalEvent = async (event, reason) => {
1184
+ const error = normalizeFatalProcessError(reason);
1185
+ api.logger.debug(`[${options.label}] Fatal ${event}`, error);
1186
+ if (shuttingDown) {
1187
+ api.logger.debug(`[${options.label}] Ignoring duplicate fatal ${event} while shutdown is already in progress`);
1188
+ return;
1189
+ }
1190
+ shuttingDown = true;
1191
+ try {
1192
+ await options.cleanup({ event, error });
1193
+ } catch (cleanupError) {
1194
+ api.logger.debug(`[${options.label}] Fatal cleanup failed`, cleanupError);
1195
+ }
1196
+ exit(1);
1197
+ };
1198
+ const onUncaughtException = (error) => {
1199
+ void handleFatalEvent("uncaughtException", error);
1200
+ };
1201
+ const onUnhandledRejection = (reason) => {
1202
+ void handleFatalEvent("unhandledRejection", reason);
1203
+ };
1204
+ target.on("uncaughtException", onUncaughtException);
1205
+ target.on("unhandledRejection", onUnhandledRejection);
1206
+ return () => {
1207
+ if (disposed) {
1208
+ return;
1209
+ }
1210
+ disposed = true;
1211
+ target.off("uncaughtException", onUncaughtException);
1212
+ target.off("unhandledRejection", onUnhandledRejection);
1213
+ };
1214
+ }
1215
+
1160
1216
  function resolveInitialCodexPermissionMode(opts) {
1161
1217
  if (opts.permissionMode) {
1162
1218
  return opts.permissionMode;
@@ -1298,30 +1354,49 @@ async function runCodex(opts) {
1298
1354
  let loopError;
1299
1355
  let closeError;
1300
1356
  let observerCloseError;
1301
- try {
1302
- exitCode = await codexLoop({
1303
- session: codexSession,
1304
- startingMode: requestedStartingMode
1305
- });
1306
- api.logger.debug(`[codex] codexLoop resolved with exit code ${exitCode}`);
1307
- } catch (error) {
1308
- loopError = error;
1309
- } finally {
1357
+ let cleanupStarted = false;
1358
+ const cleanupResources = async (closeOptions = {
1359
+ archiveOnClose: true
1360
+ }) => {
1361
+ if (cleanupStarted) {
1362
+ return;
1363
+ }
1364
+ cleanupStarted = true;
1310
1365
  try {
1311
- await index.closeProviderSession(sessionClient, {
1312
- archiveOnClose: true
1313
- });
1366
+ await index.closeProviderSession(sessionClient, closeOptions);
1314
1367
  } catch (error) {
1315
- closeError = error;
1368
+ closeError = closeError ?? error;
1316
1369
  }
1317
1370
  try {
1318
1371
  await userScopedObserver?.close();
1319
1372
  } catch (error) {
1320
- observerCloseError = error;
1373
+ observerCloseError = observerCloseError ?? error;
1321
1374
  }
1322
1375
  index.stopCaffeinate();
1323
1376
  reconnectionHandle?.cancel();
1324
- codexSession.cleanup();
1377
+ codexSession?.cleanup();
1378
+ };
1379
+ const disposeFatalProcessHandlers = installFatalProcessHandlers({
1380
+ label: "codex",
1381
+ cleanup: async ({ event, error }) => {
1382
+ await cleanupResources({
1383
+ archiveReason: `Fatal ${event}: ${error.message}`
1384
+ });
1385
+ }
1386
+ });
1387
+ try {
1388
+ exitCode = await codexLoop({
1389
+ session: codexSession,
1390
+ startingMode: requestedStartingMode
1391
+ });
1392
+ api.logger.debug(`[codex] codexLoop resolved with exit code ${exitCode}`);
1393
+ } catch (error) {
1394
+ loopError = error;
1395
+ } finally {
1396
+ disposeFatalProcessHandlers();
1397
+ await cleanupResources({
1398
+ archiveOnClose: true
1399
+ });
1325
1400
  }
1326
1401
  if (loopError !== void 0) {
1327
1402
  api.logger.debug("[codex] runCodex exiting after loop error", loopError);
@@ -3,10 +3,10 @@
3
3
  var ink = require('ink');
4
4
  var React = require('react');
5
5
  var node_crypto = require('node:crypto');
6
- var api = require('./api-CdGT5hsH.cjs');
7
- var registerKillSessionHandler = require('./registerKillSessionHandler-DjxtkGMv.cjs');
8
- var index = require('./index-D_S_7bqK.cjs');
9
- var BaseReasoningProcessor = require('./BaseReasoningProcessor-iSuaFeZH.cjs');
6
+ var api = require('./api-CeIpGPqs.cjs');
7
+ var registerKillSessionHandler = require('./registerKillSessionHandler-DECzSYvQ.cjs');
8
+ var index = require('./index-D68EOBHW.cjs');
9
+ var BaseReasoningProcessor = require('./BaseReasoningProcessor-CbqNgi4p.cjs');
10
10
  require('cross-spawn');
11
11
  require('@agentclientprotocol/sdk');
12
12
  require('ps-list');
@@ -17,7 +17,7 @@ require('node:child_process');
17
17
  require('node:readline');
18
18
  require('tweetnacl');
19
19
  require('axios');
20
- require('./persistence-CMvrZ4SA.cjs');
20
+ require('./persistence-Czyd-Uei.cjs');
21
21
  require('open');
22
22
  require('chalk');
23
23
  require('fs');
@@ -677,6 +677,7 @@ async function runGemini(opts) {
677
677
  let shouldInjectHistoryOnNextSession = false;
678
678
  let currentModeHash = null;
679
679
  let unexpectedRuntimeStopRecovery = null;
680
+ let readyAlreadySent = false;
680
681
  async function handleAbort() {
681
682
  api.logger.debug("[Gemini] Abort requested - stopping current task");
682
683
  if (!turnAbortedSent) {
@@ -1102,6 +1103,10 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
1102
1103
  let message = pending;
1103
1104
  pending = null;
1104
1105
  if (!message) {
1106
+ if (!shouldExit && messageQueue.size() === 0 && !readyAlreadySent) {
1107
+ sendReady();
1108
+ readyAlreadySent = true;
1109
+ }
1105
1110
  api.logger.debug("[gemini] Main loop: waiting for messages from queue...");
1106
1111
  const waitSignal = abortController.signal;
1107
1112
  const batch = await messageQueue.waitForMessagesAndGetAsString(waitSignal);
@@ -1136,6 +1141,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
1136
1141
  currentModeHash = message.hash;
1137
1142
  }
1138
1143
  currentModeHash = message.hash;
1144
+ readyAlreadySent = false;
1139
1145
  const userMessageToShow = message.mode?.originalUserMessage || message.message;
1140
1146
  messageBuffer.addMessage(userMessageToShow, "user");
1141
1147
  isProcessingMessage = true;
@@ -1,10 +1,10 @@
1
1
  import { useStdout, useInput, Box, Text, render } from 'ink';
2
2
  import React, { useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { randomUUID } from 'node:crypto';
4
- import { l as logger, b as connectionState, A as ApiClient } from './api-BYKV7vX6.mjs';
5
- import { B as BasePermissionHandler, C as ConversationHistory$1, r as resolveHappyOrgQueuedTurn, e as ensureManagedProviderMachine, M as MissingMachineIdError, s as syncControlledByUserState, b as MessageQueue2, h as hashObject, c as registerKillSessionHandler, d as MessageBuffer, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurn, l as launchRuntimeHandleWithFactoryResult, j as inferToolResultError, k as forwardAgentMessageToProviderSession } from './registerKillSessionHandler-5DVlZaJx.mjs';
6
- import { g as getInitialGeminiModel, r as readGeminiLocalConfig, G as GEMINI_MODEL_ENV, b as closeProviderSession, s as saveGeminiModelToConfig, d as createGeminiBackend, e as stopCaffeinate } from './index-BAhlFq45.mjs';
7
- import { B as BaseReasoningProcessor, b as bootstrapManagedProviderSession } from './BaseReasoningProcessor-C0A6Jr8V.mjs';
4
+ import { l as logger, b as connectionState, A as ApiClient } from './api-DRdn4-dL.mjs';
5
+ import { B as BasePermissionHandler, C as ConversationHistory$1, r as resolveHappyOrgQueuedTurn, e as ensureManagedProviderMachine, M as MissingMachineIdError, s as syncControlledByUserState, b as MessageQueue2, h as hashObject, c as registerKillSessionHandler, d as MessageBuffer, f as buildHappyOrgTurnPrompt, w as waitForResponseCompleteWithAbort, i as finalizeHappyOrgTurn, l as launchRuntimeHandleWithFactoryResult, j as inferToolResultError, k as forwardAgentMessageToProviderSession } from './registerKillSessionHandler-Dg0DFPae.mjs';
6
+ import { g as getInitialGeminiModel, r as readGeminiLocalConfig, G as GEMINI_MODEL_ENV, b as closeProviderSession, s as saveGeminiModelToConfig, d as createGeminiBackend, e as stopCaffeinate } from './index-C4S85XB7.mjs';
7
+ import { B as BaseReasoningProcessor, b as bootstrapManagedProviderSession } from './BaseReasoningProcessor-DJ9zxAdt.mjs';
8
8
  import 'cross-spawn';
9
9
  import '@agentclientprotocol/sdk';
10
10
  import 'ps-list';
@@ -15,7 +15,7 @@ import 'node:child_process';
15
15
  import 'node:readline';
16
16
  import 'tweetnacl';
17
17
  import 'axios';
18
- import './persistence-B8Wgn6aN.mjs';
18
+ import './persistence-DgpGouOO.mjs';
19
19
  import 'open';
20
20
  import 'chalk';
21
21
  import 'fs';
@@ -675,6 +675,7 @@ async function runGemini(opts) {
675
675
  let shouldInjectHistoryOnNextSession = false;
676
676
  let currentModeHash = null;
677
677
  let unexpectedRuntimeStopRecovery = null;
678
+ let readyAlreadySent = false;
678
679
  async function handleAbort() {
679
680
  logger.debug("[Gemini] Abort requested - stopping current task");
680
681
  if (!turnAbortedSent) {
@@ -1100,6 +1101,10 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
1100
1101
  let message = pending;
1101
1102
  pending = null;
1102
1103
  if (!message) {
1104
+ if (!shouldExit && messageQueue.size() === 0 && !readyAlreadySent) {
1105
+ sendReady();
1106
+ readyAlreadySent = true;
1107
+ }
1103
1108
  logger.debug("[gemini] Main loop: waiting for messages from queue...");
1104
1109
  const waitSignal = abortController.signal;
1105
1110
  const batch = await messageQueue.waitForMessagesAndGetAsString(waitSignal);
@@ -1134,6 +1139,7 @@ Guide: https://goo.gle/gemini-cli-auth-docs#workspace-gca`;
1134
1139
  currentModeHash = message.hash;
1135
1140
  }
1136
1141
  currentModeHash = message.hash;
1142
+ readyAlreadySent = false;
1137
1143
  const userMessageToShow = message.mode?.originalUserMessage || message.message;
1138
1144
  messageBuffer.addMessage(userMessageToShow, "user");
1139
1145
  isProcessingMessage = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happy-imou-cloud",
3
- "version": "2.1.7",
3
+ "version": "2.1.8",
4
4
  "description": "hicloud - Imou 企业定制版。关键是 happy!移动端远程 AI 编程工具,支持 Claude Code、Codex 和 Gemini CLI",
5
5
  "author": "long.zhu",
6
6
  "license": "MIT",
@@ -1,9 +1,9 @@
1
- # CLI Devtools
2
-
3
- 这组脚本用于 CLI 本地开发辅助。
4
-
5
- 当前包含:
6
-
7
- - mock credentials 生成器
8
-
9
- 新增 CLI 专属开发脚本应优先放在这里。
1
+ # CLI Devtools
2
+
3
+ 这组脚本用于 CLI 本地开发辅助。
4
+
5
+ 当前包含:
6
+
7
+ - mock credentials 生成器
8
+
9
+ 新增 CLI 专属开发脚本应优先放在这里。