happy-imou-cloud 2.1.44 → 2.1.47

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 (25) hide show
  1. package/dist/{BaseReasoningProcessor-CMyFNQ1O.cjs → BaseReasoningProcessor-CBbzF7oj.cjs} +2 -2
  2. package/dist/{BaseReasoningProcessor-DVSN7PCw.mjs → BaseReasoningProcessor-KXIi0QF_.mjs} +2 -2
  3. package/dist/{ProviderSelectionHandler-Dqa4j1pD.cjs → ProviderSelectionHandler-CJLlwlAu.cjs} +2 -2
  4. package/dist/{ProviderSelectionHandler-2IaDlDBx.mjs → ProviderSelectionHandler-DzYObYrV.mjs} +2 -2
  5. package/dist/{api-BoWVQeVe.cjs → api-CVuTajTL.cjs} +104 -1
  6. package/dist/{api-BhMVpzwg.mjs → api-D3vYIva3.mjs} +104 -2
  7. package/dist/{command-DoF8oaxg.cjs → command-BZRQuZsh.cjs} +2 -3
  8. package/dist/{command-h3Rr4Abu.mjs → command-fcJ-4Yq3.mjs} +2 -3
  9. package/dist/{index-DxF1W0nt.mjs → index-Cp1I5I3U.mjs} +345 -59
  10. package/dist/{index-kIN8gN9G.cjs → index-CyW9A7hx.cjs} +323 -53
  11. package/dist/index.cjs +2 -3
  12. package/dist/index.mjs +2 -3
  13. package/dist/lib.cjs +1 -1
  14. package/dist/lib.d.cts +86 -86
  15. package/dist/lib.d.mts +86 -86
  16. package/dist/lib.mjs +1 -1
  17. package/dist/{registerKillSessionHandler-CBm2WFM0.cjs → registerKillSessionHandler-8C_Wrgor.cjs} +10 -5
  18. package/dist/{registerKillSessionHandler-Dsg63Cx6.mjs → registerKillSessionHandler-OhhMUuCQ.mjs} +10 -6
  19. package/dist/{runClaude-BpwlCyVT.mjs → runClaude-BviM1Wl5.mjs} +11 -9
  20. package/dist/{runClaude-Dq9OISKt.cjs → runClaude-CfdT_ccS.cjs} +11 -9
  21. package/dist/{runCodex-BnzErOK_.cjs → runCodex-B-t0yy4k.cjs} +496 -60
  22. package/dist/{runCodex-BMNR2hNp.mjs → runCodex-Dx3osc7U.mjs} +496 -60
  23. package/dist/{runGemini-D4Af8oH1.mjs → runGemini-CnJ75Q--.mjs} +11 -9
  24. package/dist/{runGemini-CYc9Ufxo.cjs → runGemini-DZ5-uzB9.cjs} +11 -9
  25. package/package.json +1 -1
@@ -1,28 +1,27 @@
1
1
  import{createRequire as _pkgrollCR}from"node:module";const require=_pkgrollCR(import.meta.url);import chalk from 'chalk';
2
- import { l as logger, q as encodeBase64, c as configuration, t as readCredentials, u as ensureSigningCredentials, r as readSettings, v as updateSettings, w as encodeBase64Url, m as delay, x as buildClientHeaders, y as decodeBase64, z as writeCredentialsLegacy, B as writeCredentialsDataKey, C as readDaemonState, D as HAPPY_CLOUD_DAEMON_PORT, E as clearDaemonState, F as packageJson, i as isAuthenticationRequiredError, G as acquireDaemonLock, I as writeDaemonState, A as ApiClient, J as releaseDaemonLock, K as validateProfileForAgent, L as getProfileEnvironmentVariables, M as clearCredentials, N as clearMachineId, O as readHappyOrgDispatchTruthSnapshot, P as processHappyOrgRepoRequests, Q as readHappyOrgRepoTaskBoard, R as HappyOrgTurnReportSchema, S as recordHappyOrgTurnReport, T as MessageContentSchema, U as buildSocketAuth, V as encrypt, H as HeadTailPreviewBuffer, W as getLatestDaemonLog } from './api-BhMVpzwg.mjs';
2
+ import { l as logger, q as encodeBase64, c as configuration, t as readCredentials, u as ensureSigningCredentials, r as readSettings, v as updateSettings, w as encodeBase64Url, m as delay, x as buildClientHeaders, y as decodeBase64, z as writeCredentialsLegacy, B as writeCredentialsDataKey, C as readDaemonState, D as HAPPY_CLOUD_DAEMON_PORT, E as clearDaemonState, F as packageJson, i as isAuthenticationRequiredError, G as buildSessionRuntimeIndex, I as acquireDaemonLock, J as writeDaemonState, A as ApiClient, K as releaseDaemonLock, L as validateProfileForAgent, M as getProfileEnvironmentVariables, N as clearCredentials, O as clearMachineId, P as readHappyOrgDispatchTruthSnapshot, Q as processHappyOrgRepoRequests, R as readHappyOrgRepoTaskBoard, S as HappyOrgTurnReportSchema, T as recordHappyOrgTurnReport, U as MessageContentSchema, V as buildSocketAuth, W as encrypt, H as HeadTailPreviewBuffer, X as getLatestDaemonLog } from './api-D3vYIva3.mjs';
3
3
  import { z } from 'zod';
4
4
  import fs, { writeFile as writeFile$1, rename, unlink as unlink$1 } from 'fs/promises';
5
- import os$1, { homedir } from 'os';
6
- import * as tmp from 'tmp';
5
+ import os$1, { homedir as homedir$1 } from 'os';
7
6
  import { randomUUID, randomBytes, createCipheriv } from 'node:crypto';
8
7
  import tweetnacl from 'tweetnacl';
9
8
  import axios from 'axios';
10
9
  import qrcode from 'qrcode-terminal';
11
10
  import { writeFile, unlink, readdir, readFile, mkdir } from 'node:fs/promises';
12
11
  import { createRequire } from 'node:module';
13
- import os, { tmpdir, homedir as homedir$1 } from 'node:os';
14
- import path, { join, resolve as resolve$1, dirname as dirname$1, normalize, isAbsolute, delimiter, basename } from 'node:path';
12
+ import os, { tmpdir, homedir } from 'node:os';
13
+ import path, { join, resolve as resolve$1, dirname as dirname$1, normalize, isAbsolute, delimiter, relative, basename } from 'node:path';
15
14
  import open from 'open';
16
15
  import React, { useState } from 'react';
17
16
  import { useInput, Box, Text, render } from 'ink';
18
17
  import { spawn, execSync, exec } from 'child_process';
19
18
  import { dirname, resolve, join as join$1 } from 'path';
20
19
  import { fileURLToPath } from 'url';
21
- import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync, chmodSync, unlinkSync as unlinkSync$1, mkdirSync } from 'fs';
20
+ import { readFileSync as readFileSync$1, existsSync as existsSync$1, writeFileSync as writeFileSync$1, chmodSync, unlinkSync as unlinkSync$1, mkdirSync as mkdirSync$1 } from 'fs';
22
21
  import { execFileSync, spawn as spawn$2, execSync as execSync$1 } from 'node:child_process';
23
22
  import psList from 'ps-list';
24
23
  import spawn$1 from 'cross-spawn';
25
- import fs$1, { existsSync, readFileSync, readdirSync, statSync, unlinkSync, rmSync, mkdirSync as mkdirSync$1, mkdtempSync, cpSync, realpathSync } from 'node:fs';
24
+ import fs$1, { existsSync, readFileSync, readdirSync, statSync, unlinkSync, mkdirSync, writeFileSync, cpSync, rmSync, mkdtempSync, realpathSync } from 'node:fs';
26
25
  import fastify from 'fastify';
27
26
  import { validatorCompiler, serializerCompiler } from 'fastify-type-provider-zod';
28
27
  import { randomUUID as randomUUID$1, randomBytes as randomBytes$1, createHash } from 'crypto';
@@ -2830,16 +2829,27 @@ function createSessionMetadata(opts) {
2830
2829
  };
2831
2830
  }
2832
2831
 
2832
+ function archiveManagedSessionWithObserver(opts) {
2833
+ if (!opts.userScopedObserver || !opts.sessionIndex) {
2834
+ return false;
2835
+ }
2836
+ return opts.userScopedObserver.syncSessionRuntimeIndex(opts.sessionId, {
2837
+ ...opts.sessionIndex,
2838
+ lifecycleState: "archived"
2839
+ }, {
2840
+ markInactive: true
2841
+ });
2842
+ }
2833
2843
  async function archiveManagedSessionById(opts) {
2834
2844
  try {
2835
- const sessionClient = opts.api.sessionSyncClient({ id: opts.sessionId });
2845
+ const sessionClient = opts.api.sessionSyncClient(opts.session);
2836
2846
  await closeProviderSession(sessionClient, {
2837
2847
  archiveReason: opts.archiveReason,
2838
2848
  archivedBy: "daemon"
2839
2849
  });
2840
2850
  } catch (error) {
2841
2851
  logger.debug(
2842
- `[DAEMON RUN] Failed to archive managed session ${opts.sessionId}: ${opts.archiveReason}`,
2852
+ `[DAEMON RUN] Failed to archive managed session ${opts.session.id}: ${opts.archiveReason}`,
2843
2853
  error
2844
2854
  );
2845
2855
  }
@@ -2868,7 +2878,7 @@ async function precreateDaemonManagedSession(opts) {
2868
2878
  async function archivePrecreatedManagedSession(opts) {
2869
2879
  await archiveManagedSessionById({
2870
2880
  api: opts.api,
2871
- sessionId: opts.session.id,
2881
+ session: opts.session,
2872
2882
  archiveReason: opts.archiveReason
2873
2883
  });
2874
2884
  }
@@ -2877,11 +2887,15 @@ async function archiveDetachedManagedSessionIfNeeded(opts) {
2877
2887
  if (trackedSession.startedBy !== "daemon" || !trackedSession.happySessionId || trackedSession.happySessionMetadataFromLocalWebhook || trackedSession.skipDetachedManagedSessionArchive) {
2878
2888
  return false;
2879
2889
  }
2880
- await archiveManagedSessionById({
2881
- api: opts.api,
2890
+ if (!archiveManagedSessionWithObserver({
2891
+ userScopedObserver: opts.userScopedObserver,
2882
2892
  sessionId: trackedSession.happySessionId,
2883
- archiveReason: opts.archiveReason
2884
- });
2893
+ sessionIndex: trackedSession.sessionIndex
2894
+ })) {
2895
+ logger.debug(
2896
+ `[DAEMON RUN] Detached managed session ${trackedSession.happySessionId} cannot be archived because runtime index sync is unavailable`
2897
+ );
2898
+ }
2885
2899
  return true;
2886
2900
  }
2887
2901
 
@@ -2959,6 +2973,7 @@ function createTrackedSessionFromRemoteIndexEntry(entry) {
2959
2973
  return {
2960
2974
  startedBy,
2961
2975
  happySessionId: entry.id,
2976
+ sessionIndex: entry.sessionIndex ?? null,
2962
2977
  pid: entry.sessionIndex?.hostPid ?? 0
2963
2978
  };
2964
2979
  }
@@ -2985,6 +3000,7 @@ async function recoverTrackedSessionsFromRemoteIndex({
2985
3000
  machineId,
2986
3001
  trackedSessionPids,
2987
3002
  trackSession,
3003
+ removeTrackedSession,
2988
3004
  userScopedObserver,
2989
3005
  lookupHappyProcessByPid = findHappyProcessByPid,
2990
3006
  archiveStaleSessions = true,
@@ -2999,7 +3015,13 @@ async function recoverTrackedSessionsFromRemoteIndex({
2999
3015
  for (const session of sessions) {
3000
3016
  const sessionIndex = session.sessionIndex;
3001
3017
  const pid = sessionIndex?.hostPid;
3002
- if (!sessionIndex || sessionIndex.machineId !== machineId || typeof pid !== "number" || sessionIndex.lifecycleState === "archived") {
3018
+ if (!sessionIndex || sessionIndex.machineId !== machineId || typeof pid !== "number") {
3019
+ continue;
3020
+ }
3021
+ if (sessionIndex.lifecycleState === "archived" || session.active === false) {
3022
+ if (alreadyTracked.has(pid)) {
3023
+ removeTrackedSession?.(pid, session.id);
3024
+ }
3003
3025
  continue;
3004
3026
  }
3005
3027
  if (alreadyTracked.has(pid)) {
@@ -3039,6 +3061,7 @@ async function recoverTrackedSessionsFromRemoteIndex({
3039
3061
  }
3040
3062
  const archived = await archiveStaleRemoteSession(userScopedObserver, session);
3041
3063
  if (archived) {
3064
+ removeTrackedSession?.(pid, session.id);
3042
3065
  archivedStaleCount++;
3043
3066
  } else {
3044
3067
  skippedStaleCount++;
@@ -3107,6 +3130,7 @@ function createTrackedSessionFromRegistryEntry(entry) {
3107
3130
  startedBy: metadata.startedBy === "daemon" ? "daemon" : "happy directly - likely by user from terminal",
3108
3131
  happySessionId: entry.sessionId,
3109
3132
  happySessionMetadataFromLocalWebhook: metadata,
3133
+ sessionIndex: buildSessionRuntimeIndex(metadata),
3110
3134
  pid: entry.pid
3111
3135
  };
3112
3136
  }
@@ -3384,6 +3408,50 @@ function resolveTrackedHappySessionId(opts) {
3384
3408
  return opts.precreatedSessionId ?? opts.requestedSessionId;
3385
3409
  }
3386
3410
 
3411
+ const CODEX_HOME_CONFIG_FILES = [
3412
+ "config.toml",
3413
+ "cap_sid",
3414
+ "version.json",
3415
+ "MEMORY.md"
3416
+ ];
3417
+ const CODEX_HOME_CONFIG_DIRS = [
3418
+ "rules",
3419
+ "skills"
3420
+ ];
3421
+ function copyCodexHomeEntry$1(sourcePath, destPath) {
3422
+ if (!existsSync(sourcePath)) {
3423
+ return;
3424
+ }
3425
+ mkdirSync(dirname$1(destPath), { recursive: true });
3426
+ cpSync(sourcePath, destPath, {
3427
+ recursive: true,
3428
+ force: true,
3429
+ dereference: false,
3430
+ verbatimSymlinks: true
3431
+ });
3432
+ }
3433
+ function createDaemonCodexAuthHome(options) {
3434
+ const sourceHomeDir = options.sourceHomeDir ?? join(homedir(), ".codex");
3435
+ const targetHomeDir = options.tempDir;
3436
+ mkdirSync(targetHomeDir, { recursive: true });
3437
+ for (const fileName of CODEX_HOME_CONFIG_FILES) {
3438
+ try {
3439
+ copyCodexHomeEntry$1(join(sourceHomeDir, fileName), join(targetHomeDir, fileName));
3440
+ } catch (error) {
3441
+ logger.debug(`[codex] Failed to copy source CODEX_HOME file ${fileName} into daemon auth home`, error);
3442
+ }
3443
+ }
3444
+ for (const dirName of CODEX_HOME_CONFIG_DIRS) {
3445
+ try {
3446
+ copyCodexHomeEntry$1(join(sourceHomeDir, dirName), join(targetHomeDir, dirName));
3447
+ } catch (error) {
3448
+ logger.debug(`[codex] Failed to copy source CODEX_HOME directory ${dirName} into daemon auth home`, error);
3449
+ }
3450
+ }
3451
+ writeFileSync(join(targetHomeDir, "auth.json"), options.authJson, "utf8");
3452
+ return targetHomeDir;
3453
+ }
3454
+
3387
3455
  const DEFAULT_SESSION_WEBHOOK_TIMEOUT_MS = 45e3;
3388
3456
  const DEFAULT_TRACKED_SESSION_SWEEP_INTERVAL_MS = 5e3;
3389
3457
  function resolveSessionWebhookTimeoutMs() {
@@ -3499,11 +3567,13 @@ async function startDaemon() {
3499
3567
  const pidToTrackedSession = /* @__PURE__ */ new Map();
3500
3568
  const pidToAwaiter = /* @__PURE__ */ new Map();
3501
3569
  const getCurrentChildren = () => Array.from(pidToTrackedSession.values());
3570
+ let userScopedObserver = null;
3502
3571
  const removeTrackedSession = (pid, archiveReason) => {
3503
3572
  const trackedSession = pidToTrackedSession.get(pid);
3504
3573
  if (trackedSession && api) {
3505
3574
  void archiveDetachedManagedSessionIfNeeded({
3506
3575
  api,
3576
+ userScopedObserver,
3507
3577
  trackedSession,
3508
3578
  archiveReason
3509
3579
  });
@@ -3523,6 +3593,7 @@ async function startDaemon() {
3523
3593
  if (existingSession && existingSession.startedBy === "daemon") {
3524
3594
  existingSession.happySessionId = sessionId;
3525
3595
  existingSession.happySessionMetadataFromLocalWebhook = sessionMetadata;
3596
+ existingSession.sessionIndex = buildSessionRuntimeIndex(sessionMetadata);
3526
3597
  logger.debug(`[DAEMON RUN] Updated daemon-spawned session ${sessionId} with metadata`);
3527
3598
  const awaiter = pidToAwaiter.get(pid);
3528
3599
  if (awaiter) {
@@ -3538,6 +3609,7 @@ async function startDaemon() {
3538
3609
  startedBy: "happy directly - likely by user from terminal",
3539
3610
  happySessionId: sessionId,
3540
3611
  happySessionMetadataFromLocalWebhook: sessionMetadata,
3612
+ sessionIndex: buildSessionRuntimeIndex(sessionMetadata),
3541
3613
  pid
3542
3614
  };
3543
3615
  pidToTrackedSession.set(pid, trackedSession);
@@ -3590,9 +3662,11 @@ async function startDaemon() {
3590
3662
  const authEnv = {};
3591
3663
  if (options.token) {
3592
3664
  if (options.agent === "codex") {
3593
- const codexHomeDir = tmp.dirSync();
3594
- fs.writeFile(join$1(codexHomeDir.name, "auth.json"), options.token);
3595
- authEnv.CODEX_HOME = codexHomeDir.name;
3665
+ const codexHomeDir = await fs.mkdtemp(join$1(os$1.tmpdir(), "happy-codex-daemon-home-"));
3666
+ authEnv.CODEX_HOME = createDaemonCodexAuthHome({
3667
+ authJson: options.token,
3668
+ tempDir: codexHomeDir
3669
+ });
3596
3670
  } else {
3597
3671
  authEnv.CLAUDE_CODE_OAUTH_TOKEN = options.token;
3598
3672
  }
@@ -3696,6 +3770,7 @@ async function startDaemon() {
3696
3770
  requestedSessionId: options.sessionId,
3697
3771
  precreatedSessionId: precreatedCodexSession?.id
3698
3772
  }),
3773
+ sessionIndex: buildSessionRuntimeIndex(precreatedCodexSession?.metadata),
3699
3774
  skipDetachedManagedSessionArchive: reuseExistingManagedSession,
3700
3775
  pid: tmuxResult.pid,
3701
3776
  // Real PID from tmux -P flag
@@ -3840,6 +3915,7 @@ ${stderrSnapshot}`);
3840
3915
  requestedSessionId: options.sessionId,
3841
3916
  precreatedSessionId: precreatedCodexSession?.id
3842
3917
  }),
3918
+ sessionIndex: buildSessionRuntimeIndex(precreatedCodexSession?.metadata),
3843
3919
  skipDetachedManagedSessionArchive: reuseExistingManagedSession,
3844
3920
  pid: happyProcess.pid,
3845
3921
  childProcess: happyProcess,
@@ -4028,7 +4104,6 @@ ${stderrSnapshot}`);
4028
4104
  };
4029
4105
  api = await ApiClient.create(credentials);
4030
4106
  const activeApi = api;
4031
- let userScopedObserver = null;
4032
4107
  if (credentials.signing) {
4033
4108
  try {
4034
4109
  userScopedObserver = activeApi.userScopedObserverClient?.() ?? null;
@@ -4063,6 +4138,13 @@ ${stderrSnapshot}`);
4063
4138
  trackSession: (pid, trackedSession) => {
4064
4139
  pidToTrackedSession.set(pid, trackedSession);
4065
4140
  },
4141
+ removeTrackedSession: (pid, sessionId) => {
4142
+ const trackedSession = pidToTrackedSession.get(pid);
4143
+ if (trackedSession?.happySessionId === sessionId) {
4144
+ pidToTrackedSession.delete(pid);
4145
+ logger.debug(`[DAEMON RUN] Removed archived remote session ${sessionId} from tracking`);
4146
+ }
4147
+ },
4066
4148
  userScopedObserver,
4067
4149
  archiveStaleSessions: opts.archiveStaleSessions,
4068
4150
  skipArchivalSessionIds: pendingManagedRespawnSessionIds
@@ -4300,7 +4382,7 @@ async function install$1() {
4300
4382
  </dict>
4301
4383
  </plist>
4302
4384
  `);
4303
- writeFileSync(PLIST_FILE$1, plistContent);
4385
+ writeFileSync$1(PLIST_FILE$1, plistContent);
4304
4386
  chmodSync(PLIST_FILE$1, 420);
4305
4387
  logger.info(`Created daemon plist at ${PLIST_FILE$1}`);
4306
4388
  execSync(`launchctl load ${PLIST_FILE$1}`, { stdio: "inherit" });
@@ -5153,10 +5235,10 @@ async function handleConnectStatus() {
5153
5235
  }
5154
5236
  function updateLocalGeminiCredentials(tokens) {
5155
5237
  try {
5156
- const geminiDir = join$1(homedir(), ".gemini");
5238
+ const geminiDir = join$1(homedir$1(), ".gemini");
5157
5239
  const credentialsPath = join$1(geminiDir, "oauth_creds.json");
5158
5240
  if (!existsSync$1(geminiDir)) {
5159
- mkdirSync(geminiDir, { recursive: true });
5241
+ mkdirSync$1(geminiDir, { recursive: true });
5160
5242
  }
5161
5243
  const credentials = {
5162
5244
  access_token: tokens.access_token,
@@ -5166,7 +5248,7 @@ function updateLocalGeminiCredentials(tokens) {
5166
5248
  ...tokens.id_token && { id_token: tokens.id_token },
5167
5249
  ...tokens.expires_in && { expires_in: tokens.expires_in }
5168
5250
  };
5169
- writeFileSync(credentialsPath, JSON.stringify(credentials, null, 2), "utf-8");
5251
+ writeFileSync$1(credentialsPath, JSON.stringify(credentials, null, 2), "utf-8");
5170
5252
  console.log(chalk.gray(` Updated local credentials: ${credentialsPath}`));
5171
5253
  } catch (error) {
5172
5254
  console.log(chalk.yellow(` \u26A0\uFE0F Could not update local credentials: ${error}`));
@@ -6074,7 +6156,7 @@ function getProjectPath(workingDirectory, claudeConfigDirOverride) {
6074
6156
  const projectId = resolve$1(workingDirectory).replace(/[^a-zA-Z0-9-]/g, "-");
6075
6157
  const claudeConfigDirRaw = process.env.CLAUDE_CONFIG_DIR ?? "";
6076
6158
  const claudeConfigDirTrimmed = claudeConfigDirRaw.trim();
6077
- const claudeConfigDir = claudeConfigDirTrimmed ? claudeConfigDirTrimmed : join(homedir$1(), ".claude");
6159
+ const claudeConfigDir = claudeConfigDirTrimmed ? claudeConfigDirTrimmed : join(homedir(), ".claude");
6078
6160
  return join(claudeConfigDir, "projects", projectId);
6079
6161
  }
6080
6162
 
@@ -6139,7 +6221,7 @@ class ExitCodeError extends Error {
6139
6221
  const claudeCliPath = resolve$1(join(projectPath(), "scripts", "claude_local_launcher.cjs"));
6140
6222
  async function claudeLocal(opts) {
6141
6223
  const projectDir = getProjectPath(opts.path);
6142
- mkdirSync$1(projectDir, { recursive: true });
6224
+ mkdirSync(projectDir, { recursive: true });
6143
6225
  const hasContinueFlag = opts.claudeArgs?.includes("--continue");
6144
6226
  const hasResumeFlag = opts.claudeArgs?.includes("--resume");
6145
6227
  const hasUserSessionControl = hasContinueFlag || hasResumeFlag;
@@ -8609,11 +8691,15 @@ class AcpBackend {
8609
8691
  transport;
8610
8692
  sessionPreferences;
8611
8693
  sessionConfigOptions = null;
8694
+ agentCapabilities = null;
8612
8695
  /** Keep a short rolling stderr buffer so startup failures can surface the real cause. */
8613
8696
  recentStderrLines = [];
8614
8697
  acpMaxMultilineStdoutBytes;
8615
8698
  oversizedStdoutNoticeEmittedForCurrentTurn = false;
8616
8699
  resourceCleanupDone = false;
8700
+ getProviderSessionId() {
8701
+ return this.acpSessionId;
8702
+ }
8617
8703
  recordRecentStderr(text) {
8618
8704
  const normalized = text.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
8619
8705
  if (normalized.length === 0) {
@@ -8650,6 +8736,14 @@ class AcpBackend {
8650
8736
  updateSessionConfigOptions(configOptions) {
8651
8737
  this.sessionConfigOptions = Array.isArray(configOptions) ? configOptions : null;
8652
8738
  }
8739
+ supportsLoadSession() {
8740
+ const capabilities = this.agentCapabilities;
8741
+ return capabilities?.loadSession === true;
8742
+ }
8743
+ supportsResumeSession() {
8744
+ const capabilities = this.agentCapabilities;
8745
+ return capabilities?.sessionCapabilities?.resume != null;
8746
+ }
8653
8747
  syncSessionConfigOptionsFromUpdate(update) {
8654
8748
  const configOptions = update.configOptions;
8655
8749
  if (!Array.isArray(configOptions)) {
@@ -9231,7 +9325,7 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9231
9325
  await delay(initDelayMs);
9232
9326
  }
9233
9327
  logger.debug(`[AcpBackend] Initializing connection (timeout: ${initTimeout}ms)...`);
9234
- await withRetry(
9328
+ const initializeResponse = await withRetry(
9235
9329
  async () => {
9236
9330
  let timeoutHandle = null;
9237
9331
  try {
@@ -9272,6 +9366,7 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9272
9366
  shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
9273
9367
  }
9274
9368
  );
9369
+ this.agentCapabilities = initializeResponse.agentCapabilities ?? null;
9275
9370
  logger.debug(`[AcpBackend] Initialize completed`);
9276
9371
  const mcpServers = this.options.mcpServers ? Object.entries(this.options.mcpServers).map(([name, config]) => ({
9277
9372
  name,
@@ -9283,7 +9378,21 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9283
9378
  cwd: this.options.cwd,
9284
9379
  mcpServers
9285
9380
  };
9286
- logger.debug(`[AcpBackend] Creating new session...`);
9381
+ const requestedResumeSessionId = typeof this.options.resumeSessionId === "string" && this.options.resumeSessionId.trim() ? this.options.resumeSessionId.trim() : null;
9382
+ const sessionOperation = requestedResumeSessionId && this.supportsResumeSession() ? "resume" : requestedResumeSessionId && this.supportsLoadSession() ? "load" : "new";
9383
+ const sessionRequest = sessionOperation === "resume" ? {
9384
+ cwd: this.options.cwd,
9385
+ mcpServers,
9386
+ sessionId: requestedResumeSessionId
9387
+ } : sessionOperation === "load" ? {
9388
+ cwd: this.options.cwd,
9389
+ mcpServers,
9390
+ sessionId: requestedResumeSessionId
9391
+ } : newSessionRequest;
9392
+ if (requestedResumeSessionId && sessionOperation === "new") {
9393
+ throw new Error("ACP agent does not support session resume/load; refusing to fork the Codex conversation");
9394
+ }
9395
+ logger.debug(`[AcpBackend] ${sessionOperation === "new" ? "Creating new" : `${sessionOperation === "resume" ? "Resuming" : "Loading"} existing`} session...`);
9287
9396
  const sessionResponse = await withRetry(
9288
9397
  async () => {
9289
9398
  let timeoutHandle = null;
@@ -9291,7 +9400,7 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9291
9400
  const result = await raceWithProcessExit(
9292
9401
  this.process,
9293
9402
  () => Promise.race([
9294
- this.connection.newSession(newSessionRequest).then((res) => {
9403
+ (sessionOperation === "resume" ? this.connection.resumeSession(sessionRequest) : sessionOperation === "load" ? this.connection.loadSession(sessionRequest) : this.connection.newSession(sessionRequest)).then((res) => {
9295
9404
  if (timeoutHandle) {
9296
9405
  clearTimeout(timeoutHandle);
9297
9406
  timeoutHandle = null;
@@ -9318,14 +9427,14 @@ Recent stderr: ${recentStderrSummaryLine}` : `Signal: ${signal}`;
9318
9427
  }
9319
9428
  },
9320
9429
  {
9321
- operationName: "NewSession",
9430
+ operationName: sessionOperation === "resume" ? "ResumeSession" : sessionOperation === "load" ? "LoadSession" : "NewSession",
9322
9431
  maxAttempts: RETRY_CONFIG.maxAttempts,
9323
9432
  baseDelayMs: RETRY_CONFIG.baseDelayMs,
9324
9433
  maxDelayMs: RETRY_CONFIG.maxDelayMs,
9325
9434
  shouldRetry: (error) => !(error instanceof AcpProcessStartupError)
9326
9435
  }
9327
9436
  );
9328
- this.acpSessionId = sessionResponse.sessionId;
9437
+ this.acpSessionId = requestedResumeSessionId ?? sessionResponse.sessionId;
9329
9438
  this.updateSessionConfigOptions(sessionResponse.configOptions);
9330
9439
  logger.debug(`[AcpBackend] Session created: ${this.acpSessionId}`);
9331
9440
  await this.applySessionConfigPresets();
@@ -9718,12 +9827,12 @@ function readGeminiLocalConfig() {
9718
9827
  let googleCloudProject = null;
9719
9828
  let googleCloudProjectEmail = null;
9720
9829
  const possiblePaths = [
9721
- join$1(homedir(), ".gemini", "oauth_creds.json"),
9830
+ join$1(homedir$1(), ".gemini", "oauth_creds.json"),
9722
9831
  // Main OAuth credentials file
9723
- join$1(homedir(), ".gemini", "config.json"),
9724
- join$1(homedir(), ".config", "gemini", "config.json"),
9725
- join$1(homedir(), ".gemini", "auth.json"),
9726
- join$1(homedir(), ".config", "gemini", "auth.json")
9832
+ join$1(homedir$1(), ".gemini", "config.json"),
9833
+ join$1(homedir$1(), ".config", "gemini", "config.json"),
9834
+ join$1(homedir$1(), ".gemini", "auth.json"),
9835
+ join$1(homedir$1(), ".config", "gemini", "auth.json")
9727
9836
  ];
9728
9837
  for (const configPath of possiblePaths) {
9729
9838
  if (existsSync$1(configPath)) {
@@ -9801,10 +9910,10 @@ function determineGeminiModel(explicitModel, localConfig) {
9801
9910
  }
9802
9911
  function saveGeminiModelToConfig(model) {
9803
9912
  try {
9804
- const configDir = join$1(homedir(), ".gemini");
9913
+ const configDir = join$1(homedir$1(), ".gemini");
9805
9914
  const configPath = join$1(configDir, "config.json");
9806
9915
  if (!existsSync$1(configDir)) {
9807
- mkdirSync(configDir, { recursive: true });
9916
+ mkdirSync$1(configDir, { recursive: true });
9808
9917
  }
9809
9918
  let config = {};
9810
9919
  if (existsSync$1(configPath)) {
@@ -9816,7 +9925,7 @@ function saveGeminiModelToConfig(model) {
9816
9925
  }
9817
9926
  }
9818
9927
  config.model = model;
9819
- writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
9928
+ writeFileSync$1(configPath, JSON.stringify(config, null, 2), "utf-8");
9820
9929
  logger.debug(`[Gemini] Saved model "${model}" to ${configPath}`);
9821
9930
  } catch (error) {
9822
9931
  logger.debug(`[Gemini] Failed to save model to config:`, error);
@@ -9824,10 +9933,10 @@ function saveGeminiModelToConfig(model) {
9824
9933
  }
9825
9934
  function saveGoogleCloudProjectToConfig(projectId, email) {
9826
9935
  try {
9827
- const configDir = join$1(homedir(), ".gemini");
9936
+ const configDir = join$1(homedir$1(), ".gemini");
9828
9937
  const configPath = join$1(configDir, "config.json");
9829
9938
  if (!existsSync$1(configDir)) {
9830
- mkdirSync(configDir, { recursive: true });
9939
+ mkdirSync$1(configDir, { recursive: true });
9831
9940
  }
9832
9941
  let config = {};
9833
9942
  if (existsSync$1(configPath)) {
@@ -9841,7 +9950,7 @@ function saveGoogleCloudProjectToConfig(projectId, email) {
9841
9950
  if (email) {
9842
9951
  config.googleCloudProjectEmail = email;
9843
9952
  }
9844
- writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
9953
+ writeFileSync$1(configPath, JSON.stringify(config, null, 2), "utf-8");
9845
9954
  logger.debug(`[Gemini] Saved Google Cloud Project "${projectId}"${email ? ` for ${email}` : ""} to ${configPath}`);
9846
9955
  } catch (error) {
9847
9956
  logger.debug(`[Gemini] Failed to save Google Cloud Project to config:`, error);
@@ -10004,8 +10113,23 @@ function readCodexAcpConfigOverrides() {
10004
10113
  const raw = readFirstEnv("HAPPY_CODEX_ACP_CONFIG_OVERRIDES", "HAPPIER_CODEX_ACP_CONFIG_OVERRIDES");
10005
10114
  return raw.split("\n").map((line) => line.trim()).filter(Boolean);
10006
10115
  }
10116
+ function sanitizeCodexAcpBaseArgs(baseArgs = []) {
10117
+ const sanitized = [];
10118
+ for (let index = 0; index < baseArgs.length; index += 1) {
10119
+ const arg = baseArgs[index];
10120
+ if (arg === "--dangerously-bypass-approvals-and-sandbox" || arg === "--yolo" || arg.startsWith("--ask-for-approval=") || arg.startsWith("--approval-policy=") || arg.startsWith("--sandbox=")) {
10121
+ continue;
10122
+ }
10123
+ if (arg === "--ask-for-approval" || arg === "--approval-policy" || arg === "--sandbox") {
10124
+ index += 1;
10125
+ continue;
10126
+ }
10127
+ sanitized.push(arg);
10128
+ }
10129
+ return sanitized;
10130
+ }
10007
10131
  function buildCodexAcpConfigArgs(options) {
10008
- const args = [...options.baseArgs ?? []];
10132
+ const args = sanitizeCodexAcpBaseArgs(options.baseArgs);
10009
10133
  const overrides = [...readCodexAcpConfigOverrides()];
10010
10134
  if (options.model) {
10011
10135
  overrides.push(`model=${JSON.stringify(options.model)}`);
@@ -10134,6 +10258,9 @@ function resolveCodexExecutable() {
10134
10258
  }
10135
10259
  return "codex";
10136
10260
  }
10261
+ function shouldUseShellForCodex(executable) {
10262
+ return process.platform === "win32" && /\.(cmd|bat|ps1)$/i.test(executable);
10263
+ }
10137
10264
 
10138
10265
  const CODEX_HOME_SEED_FILES = [
10139
10266
  "auth.json",
@@ -10147,6 +10274,24 @@ const CODEX_HOME_SEED_DIRS = [
10147
10274
  ];
10148
10275
  const MAX_CODEX_SKILL_DESCRIPTION_LENGTH = 1024;
10149
10276
  const MANAGED_CODEX_HOME_PREFIX = "happy-codex-home-";
10277
+ function isPlainObject(value) {
10278
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10279
+ }
10280
+ function isApiKeyOnlyCodexAuth(value) {
10281
+ if (!isPlainObject(value)) {
10282
+ return false;
10283
+ }
10284
+ const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0 && entryValue !== null);
10285
+ return entries.length === 1 && typeof value.OPENAI_API_KEY === "string" && value.OPENAI_API_KEY.trim().length > 0;
10286
+ }
10287
+ function shouldUseSourceCodexHomeForMutableAuth(sourceHomeDir) {
10288
+ try {
10289
+ const auth = JSON.parse(readFileSync(join(sourceHomeDir, "auth.json"), "utf8"));
10290
+ return !isApiKeyOnlyCodexAuth(auth);
10291
+ } catch {
10292
+ return false;
10293
+ }
10294
+ }
10150
10295
  function getCodexPlatformTarget(platform, arch) {
10151
10296
  if (platform === "win32" && arch === "x64") {
10152
10297
  return {
@@ -10310,7 +10455,7 @@ function copyCodexHomeEntry(sourcePath, destPath) {
10310
10455
  if (!existsSync(sourcePath)) {
10311
10456
  return;
10312
10457
  }
10313
- mkdirSync$1(dirname$1(destPath), { recursive: true });
10458
+ mkdirSync(dirname$1(destPath), { recursive: true });
10314
10459
  cpSync(sourcePath, destPath, {
10315
10460
  recursive: true,
10316
10461
  force: true,
@@ -10394,7 +10539,7 @@ function seedCodexSkillEntries(sourceSkillsDir, isolatedHomeDir, sourceLabel) {
10394
10539
  return;
10395
10540
  }
10396
10541
  const destSkillsDir = join(isolatedHomeDir, "skills");
10397
- mkdirSync$1(destSkillsDir, { recursive: true });
10542
+ mkdirSync(destSkillsDir, { recursive: true });
10398
10543
  for (const entryName of readdirSync(sourceSkillsDir)) {
10399
10544
  const sourceEntryPath = join(sourceSkillsDir, entryName);
10400
10545
  if (!shouldSeedCodexSkillEntry(sourceEntryPath)) {
@@ -10410,7 +10555,135 @@ function seedCodexSkillEntries(sourceSkillsDir, isolatedHomeDir, sourceLabel) {
10410
10555
  }
10411
10556
  }
10412
10557
  }
10413
- function seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir) {
10558
+ function isWithinDirectory(parentDir, childPath, platform) {
10559
+ const normalizedParent = normalizePathForComparison(parentDir, platform);
10560
+ const normalizedChild = normalizePathForComparison(childPath, platform);
10561
+ return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);
10562
+ }
10563
+ function extractCodexSessionIdFromFilePath(filePath) {
10564
+ const match = filePath.match(/-([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})\.jsonl$/);
10565
+ return match?.[1] ?? null;
10566
+ }
10567
+ function findCodexSessionFile(sourceHomeDir, resumeSessionId, platform) {
10568
+ const sessionsRoot = join(sourceHomeDir, "sessions");
10569
+ const stack = [sessionsRoot];
10570
+ let bestMatch = null;
10571
+ while (stack.length > 0) {
10572
+ const currentDir = stack.pop();
10573
+ let entries;
10574
+ try {
10575
+ entries = readdirSync(currentDir, { withFileTypes: true });
10576
+ } catch {
10577
+ continue;
10578
+ }
10579
+ for (const entry of entries) {
10580
+ const fullPath = join(currentDir, entry.name);
10581
+ if (!isWithinDirectory(sessionsRoot, fullPath, platform)) {
10582
+ continue;
10583
+ }
10584
+ if (entry.isDirectory()) {
10585
+ stack.push(fullPath);
10586
+ continue;
10587
+ }
10588
+ if (!entry.isFile() || extractCodexSessionIdFromFilePath(fullPath) !== resumeSessionId) {
10589
+ continue;
10590
+ }
10591
+ try {
10592
+ const mtimeMs = statSync(fullPath).mtimeMs;
10593
+ if (!bestMatch || mtimeMs > bestMatch.mtimeMs) {
10594
+ bestMatch = { path: fullPath, mtimeMs };
10595
+ }
10596
+ } catch {
10597
+ }
10598
+ }
10599
+ }
10600
+ return bestMatch?.path ?? null;
10601
+ }
10602
+ function seedCodexResumeSessionFile(sourceHomeDir, isolatedHomeDir, resumeSessionId, platform) {
10603
+ const normalizedResumeSessionId = typeof resumeSessionId === "string" && resumeSessionId.trim() ? resumeSessionId.trim() : null;
10604
+ if (!normalizedResumeSessionId) {
10605
+ return;
10606
+ }
10607
+ const sourceSessionFile = findCodexSessionFile(sourceHomeDir, normalizedResumeSessionId, platform);
10608
+ if (!sourceSessionFile) {
10609
+ logger.debug(`[codex] No source CODEX_HOME session file found for resume id ${normalizedResumeSessionId}`);
10610
+ return;
10611
+ }
10612
+ const sourceSessionsRoot = join(sourceHomeDir, "sessions");
10613
+ const relativeSessionPath = relative(sourceSessionsRoot, sourceSessionFile);
10614
+ if (!relativeSessionPath || relativeSessionPath.startsWith("..") || isAbsolute(relativeSessionPath)) {
10615
+ logger.debug(`[codex] Refusing to seed CODEX_HOME session outside sessions root: ${sourceSessionFile}`);
10616
+ return;
10617
+ }
10618
+ try {
10619
+ copyCodexHomeEntry(
10620
+ sourceSessionFile,
10621
+ join(isolatedHomeDir, "sessions", relativeSessionPath)
10622
+ );
10623
+ } catch (error) {
10624
+ logger.debug(`[codex] Failed to seed CODEX_HOME session file for ${normalizedResumeSessionId}`, error);
10625
+ }
10626
+ }
10627
+ function shouldSyncCodexSessionFileBack(sourcePath, destPath) {
10628
+ let sourceStat;
10629
+ try {
10630
+ sourceStat = statSync(sourcePath);
10631
+ } catch {
10632
+ return false;
10633
+ }
10634
+ if (!sourceStat.isFile()) {
10635
+ return false;
10636
+ }
10637
+ let destStat;
10638
+ try {
10639
+ destStat = statSync(destPath);
10640
+ } catch {
10641
+ return true;
10642
+ }
10643
+ return sourceStat.mtimeMs >= destStat.mtimeMs || sourceStat.size !== destStat.size;
10644
+ }
10645
+ function syncCodexSessionFilesBackToSource(isolatedHomeDir, sourceHomeDir, platform) {
10646
+ const isolatedSessionsRoot = join(isolatedHomeDir, "sessions");
10647
+ const sourceSessionsRoot = join(sourceHomeDir, "sessions");
10648
+ const stack = [isolatedSessionsRoot];
10649
+ while (stack.length > 0) {
10650
+ const currentDir = stack.pop();
10651
+ let entries;
10652
+ try {
10653
+ entries = readdirSync(currentDir, { withFileTypes: true });
10654
+ } catch {
10655
+ continue;
10656
+ }
10657
+ for (const entry of entries) {
10658
+ const fullPath = join(currentDir, entry.name);
10659
+ if (!isWithinDirectory(isolatedSessionsRoot, fullPath, platform)) {
10660
+ continue;
10661
+ }
10662
+ if (entry.isDirectory()) {
10663
+ stack.push(fullPath);
10664
+ continue;
10665
+ }
10666
+ if (!entry.isFile() || extractCodexSessionIdFromFilePath(fullPath) === null) {
10667
+ continue;
10668
+ }
10669
+ const relativeSessionPath = relative(isolatedSessionsRoot, fullPath);
10670
+ if (!relativeSessionPath || relativeSessionPath.startsWith("..") || isAbsolute(relativeSessionPath)) {
10671
+ logger.debug(`[codex] Refusing to sync CODEX_HOME session outside sessions root: ${fullPath}`);
10672
+ continue;
10673
+ }
10674
+ const destPath = join(sourceSessionsRoot, relativeSessionPath);
10675
+ if (!shouldSyncCodexSessionFileBack(fullPath, destPath)) {
10676
+ continue;
10677
+ }
10678
+ try {
10679
+ copyCodexHomeEntry(fullPath, destPath);
10680
+ } catch (error) {
10681
+ logger.debug(`[codex] Failed to sync CODEX_HOME session file back to source: ${fullPath}`, error);
10682
+ }
10683
+ }
10684
+ }
10685
+ }
10686
+ function seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir, resumeSessionId, platform) {
10414
10687
  if (existsSync(sourceHomeDir)) {
10415
10688
  for (const fileName of CODEX_HOME_SEED_FILES) {
10416
10689
  try {
@@ -10431,6 +10704,7 @@ function seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir)
10431
10704
  seedCodexSkillEntries(bundledSkillsDir, isolatedHomeDir, "bundled skills");
10432
10705
  }
10433
10706
  seedCodexSkillEntries(join(sourceHomeDir, "skills"), isolatedHomeDir, "source CODEX_HOME");
10707
+ seedCodexResumeSessionFile(sourceHomeDir, isolatedHomeDir, resumeSessionId, platform);
10434
10708
  }
10435
10709
  function prepareCodexAcpEnvironment(overrides = {}, options = {}) {
10436
10710
  const env = buildCodexAcpEnv(overrides, options);
@@ -10448,17 +10722,26 @@ function prepareCodexAcpEnvironment(overrides = {}, options = {}) {
10448
10722
  return { env };
10449
10723
  }
10450
10724
  }
10725
+ const sourceHomeDir = options.sourceHomeDir ?? join(homedir(), ".codex");
10726
+ const bundledSkillsDir = options.bundledSkillsDir ?? join(projectPath(), "skills");
10727
+ if (shouldUseSourceCodexHomeForMutableAuth(sourceHomeDir)) {
10728
+ logger.debug("[codex] Using source CODEX_HOME for mutable Codex auth credentials");
10729
+ env.CODEX_HOME = sourceHomeDir;
10730
+ return {
10731
+ env,
10732
+ codexHomePath: sourceHomeDir
10733
+ };
10734
+ }
10451
10735
  const tempDirFactory = options.tempDirFactory ?? mkdtempSync;
10452
10736
  const isolatedHomeDir = tempDirFactory(join(tmpdir(), "happy-codex-home-"));
10453
- mkdirSync$1(isolatedHomeDir, { recursive: true });
10454
- const sourceHomeDir = options.sourceHomeDir ?? join(homedir$1(), ".codex");
10455
- const bundledSkillsDir = options.bundledSkillsDir ?? join(projectPath(), "skills");
10456
- seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir);
10737
+ mkdirSync(isolatedHomeDir, { recursive: true });
10738
+ seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir, options.resumeSessionId, platform);
10457
10739
  env.CODEX_HOME = isolatedHomeDir;
10458
10740
  return {
10459
10741
  env,
10460
10742
  codexHomePath: isolatedHomeDir,
10461
10743
  cleanup: () => {
10744
+ syncCodexSessionFilesBackToSource(isolatedHomeDir, sourceHomeDir, platform);
10462
10745
  rmSync(isolatedHomeDir, { recursive: true, force: true });
10463
10746
  }
10464
10747
  };
@@ -10491,6 +10774,8 @@ function createCodexBackend(options) {
10491
10774
  const preparedEnv = prepareCodexAcpEnvironment({
10492
10775
  ...options.env,
10493
10776
  NODE_ENV: "production"
10777
+ }, {
10778
+ resumeSessionId: options.resumeSessionId
10494
10779
  });
10495
10780
  const backendOptions = {
10496
10781
  agentName: "codex",
@@ -10501,7 +10786,8 @@ function createCodexBackend(options) {
10501
10786
  permissionHandler: options.permissionHandler,
10502
10787
  selectionHandler: options.selectionHandler,
10503
10788
  transportHandler: resolveCodexTransport(spawn.command),
10504
- resourceCleanup: preparedEnv.cleanup
10789
+ resourceCleanup: preparedEnv.cleanup,
10790
+ resumeSessionId: options.resumeSessionId
10505
10791
  };
10506
10792
  return {
10507
10793
  backend: new AcpBackend(backendOptions),
@@ -10618,7 +10904,7 @@ function getGlobalClaudeVersion() {
10618
10904
  const output = execSync$1("claude --version", {
10619
10905
  encoding: "utf8",
10620
10906
  stdio: ["pipe", "pipe", "pipe"],
10621
- cwd: homedir$1(),
10907
+ cwd: homedir(),
10622
10908
  env: cleanEnv,
10623
10909
  windowsHide: true
10624
10910
  }).trim();
@@ -10655,7 +10941,7 @@ function getCleanEnv() {
10655
10941
  return env;
10656
10942
  }
10657
10943
  function findGlobalClaudePath() {
10658
- const homeDir = homedir$1();
10944
+ const homeDir = homedir();
10659
10945
  const cleanEnv = getCleanEnv();
10660
10946
  try {
10661
10947
  execSync$1("claude --version", {
@@ -11935,14 +12221,14 @@ var launch = /*#__PURE__*/Object.freeze({
11935
12221
  const unifiedProviderExecutors = {
11936
12222
  claude: async (opts) => {
11937
12223
  const claudeOptions = opts.claudeOptions ?? {};
11938
- const { runClaude } = await import('./runClaude-BpwlCyVT.mjs');
12224
+ const { runClaude } = await import('./runClaude-BviM1Wl5.mjs');
11939
12225
  await runClaude(opts.credentials, {
11940
12226
  ...claudeOptions,
11941
12227
  startingMode: claudeOptions.startingMode ?? (claudeOptions.startedBy === "daemon" ? "remote" : void 0)
11942
12228
  });
11943
12229
  },
11944
12230
  codex: async (opts) => {
11945
- const { runCodex } = await import('./runCodex-BMNR2hNp.mjs');
12231
+ const { runCodex } = await import('./runCodex-Dx3osc7U.mjs');
11946
12232
  await runCodex({
11947
12233
  credentials: opts.credentials,
11948
12234
  startedBy: opts.startedBy,
@@ -11951,7 +12237,7 @@ const unifiedProviderExecutors = {
11951
12237
  });
11952
12238
  },
11953
12239
  gemini: async (opts) => {
11954
- const { runGemini } = await import('./runGemini-D4Af8oH1.mjs');
12240
+ const { runGemini } = await import('./runGemini-CnJ75Q--.mjs');
11955
12241
  await runGemini({
11956
12242
  credentials: opts.credentials,
11957
12243
  startedBy: opts.startedBy
@@ -12034,7 +12320,7 @@ function shouldRunMainClaudeFlow(opts) {
12034
12320
  return;
12035
12321
  } else if (subcommand === "runtime") {
12036
12322
  if (args[1] === "providers") {
12037
- const { renderRuntimeProviders } = await import('./command-h3Rr4Abu.mjs');
12323
+ const { renderRuntimeProviders } = await import('./command-fcJ-4Yq3.mjs');
12038
12324
  console.log(renderRuntimeProviders());
12039
12325
  return;
12040
12326
  }
@@ -12240,8 +12526,8 @@ function shouldRunMainClaudeFlow(opts) {
12240
12526
  const projectId = args[3];
12241
12527
  try {
12242
12528
  const { saveGoogleCloudProjectToConfig } = await Promise.resolve().then(function () { return config; });
12243
- const { readCredentials: readCredentials2 } = await import('./api-BhMVpzwg.mjs').then(function (n) { return n.X; });
12244
- const { ApiClient: ApiClient2 } = await import('./api-BhMVpzwg.mjs').then(function (n) { return n.Y; });
12529
+ const { readCredentials: readCredentials2 } = await import('./api-D3vYIva3.mjs').then(function (n) { return n.Y; });
12530
+ const { ApiClient: ApiClient2 } = await import('./api-D3vYIva3.mjs').then(function (n) { return n.Z; });
12245
12531
  let userEmail = void 0;
12246
12532
  try {
12247
12533
  const credentials = await readCredentials2();
@@ -12659,4 +12945,4 @@ ${chalk.bold("Examples:")}
12659
12945
  }
12660
12946
  }
12661
12947
 
12662
- export { AbortError as A, getEnvironmentInfo as B, startCaffeinate as C, ExitCodeError as E, Future as F, GEMINI_MODEL_ENV as G, PushableAsyncIterable as P, RuntimeShell as R, createSessionMetadata as a, closeProviderSession as b, createDefaultRuntimeShell as c, createGeminiBackend as d, stopCaffeinate as e, formatDisplayMessage as f, getInitialGeminiModel as g, createCodexBackend as h, readManagedSessionTag as i, resolveManagedSessionTag as j, initialMachineMetadata as k, resolveCanonicalToolNameV2 as l, isTerminalReferenceOnlyPayload as m, getProjectPath as n, claudeLocal as o, publishSessionRegistration as p, trimIdent as q, readGeminiLocalConfig as r, saveGeminiModelToConfig as s, truncateDisplayMessage as t, createClaudeBackend as u, validateCodexAcpSpawn as v, claudeCheckSession as w, projectPath as x, mapToClaudeMode as y, query as z };
12948
+ export { AcpBackend as A, mapToClaudeMode as B, query as C, AbortError as D, ExitCodeError as E, Future as F, GEMINI_MODEL_ENV as G, getEnvironmentInfo as H, startCaffeinate as I, PushableAsyncIterable as P, RuntimeShell as R, createSessionMetadata as a, closeProviderSession as b, createDefaultRuntimeShell as c, createGeminiBackend as d, stopCaffeinate as e, formatDisplayMessage as f, getInitialGeminiModel as g, createCodexBackend as h, resolveCodexExecutable as i, shouldUseShellForCodex as j, readManagedSessionTag as k, resolveManagedSessionTag as l, initialMachineMetadata as m, resolveCanonicalToolNameV2 as n, isTerminalReferenceOnlyPayload as o, publishSessionRegistration as p, getProjectPath as q, readGeminiLocalConfig as r, saveGeminiModelToConfig as s, truncateDisplayMessage as t, claudeLocal as u, validateCodexAcpSpawn as v, trimIdent as w, createClaudeBackend as x, claudeCheckSession as y, projectPath as z };