happy-imou-cloud 2.1.49 → 2.1.51

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 (55) hide show
  1. package/dist/AcpBackend-CqO3D07V.mjs +2619 -0
  2. package/dist/AcpBackend-XPiTd6ph.cjs +2621 -0
  3. package/dist/{BaseReasoningProcessor-Dn9NcoHz.cjs → BaseReasoningProcessor-BD9tiwep.cjs} +1 -144
  4. package/dist/{BaseReasoningProcessor-CAVeOdyo.mjs → BaseReasoningProcessor-CjlayL2f.mjs} +2 -144
  5. package/dist/ConversationHistory-Bl2doTA-.cjs +780 -0
  6. package/dist/ConversationHistory-CI5bBfuA.mjs +771 -0
  7. package/dist/{ProviderSelectionHandler-BJJc7qOR.cjs → ProviderSelectionHandler-C7GE5QjX.cjs} +6 -6
  8. package/dist/{ProviderSelectionHandler-DIYidT13.mjs → ProviderSelectionHandler-uQ8jzdzr.mjs} +2 -2
  9. package/dist/RuntimeShell-BDt42io_.mjs +252 -0
  10. package/dist/RuntimeShell-D_Te12wq.cjs +258 -0
  11. package/dist/bootstrapManagedProviderSession-Bln-TwyB.cjs +147 -0
  12. package/dist/bootstrapManagedProviderSession-D2Z6YU3n.mjs +145 -0
  13. package/dist/claude-BKNT-2fG.cjs +1080 -0
  14. package/dist/claude-CnN5WCWj.mjs +1073 -0
  15. package/dist/codex-DLGP8WF6.mjs +577 -0
  16. package/dist/codex-Fv2eali8.cjs +582 -0
  17. package/dist/{command-VcH4hbhi.cjs → command-BWPlJyCN.cjs} +16 -8
  18. package/dist/{command-CzfRRhVe.mjs → command-CELwsYoG.mjs} +15 -7
  19. package/dist/config-CFL0Gkqt.cjs +184 -0
  20. package/dist/config-ChSPe7p9.mjs +174 -0
  21. package/dist/createDefaultRuntimeShell-BXu3vCvT.cjs +33 -0
  22. package/dist/createDefaultRuntimeShell-DOg6g3-G.mjs +31 -0
  23. package/dist/cursor-Blq1cHdr.cjs +91 -0
  24. package/dist/cursor-CwPNSy_A.mjs +88 -0
  25. package/dist/future-Dq4Ha1Dn.cjs +24 -0
  26. package/dist/future-xRdLl3vf.mjs +22 -0
  27. package/dist/{index-xa1kwZoj.cjs → index-B_JYgMUS.cjs} +189 -5352
  28. package/dist/{index-7Z93BoVn.mjs → index-CX-F_fuk.mjs} +177 -5331
  29. package/dist/index.cjs +2 -2
  30. package/dist/index.mjs +2 -2
  31. package/dist/installFatalProcessHandlers-0vaw9MAz.mjs +55 -0
  32. package/dist/installFatalProcessHandlers-CyURn5Bp.cjs +57 -0
  33. package/dist/launch-BoCCEd5p.mjs +63 -0
  34. package/dist/launch-wZA5BcvS.cjs +66 -0
  35. package/dist/lib.cjs +2 -3
  36. package/dist/lib.d.cts +20 -17
  37. package/dist/lib.d.mts +20 -17
  38. package/dist/lib.mjs +1 -2
  39. package/dist/resolveCommand-B3BGyBE2.mjs +189 -0
  40. package/dist/resolveCommand-DYMd9PNC.cjs +193 -0
  41. package/dist/{runClaude-zCwRhpOw.mjs → runClaude-Be0myF9k.mjs} +8 -5
  42. package/dist/{runClaude-BBGNmGj6.cjs → runClaude-DZJt5er7.cjs} +46 -43
  43. package/dist/{runCodex-BbgLVjb9.mjs → runCodex-BSnyN4m7.mjs} +226 -117
  44. package/dist/{runCodex-jUU6U2tZ.cjs → runCodex-DTCcGRue.cjs} +269 -160
  45. package/dist/runCursor-Bn1PuwJy.cjs +506 -0
  46. package/dist/runCursor-M6dQ6bGF.mjs +504 -0
  47. package/dist/{runGemini-DcwNsudA.mjs → runGemini-BNm4vYKA.mjs} +279 -5
  48. package/dist/{runGemini-C0NT8MHK.cjs → runGemini-Bn3lFhz6.cjs} +309 -35
  49. package/dist/{registerKillSessionHandler-DLDg2EES.mjs → sessionControl-1bT_7OI6.mjs} +1643 -2405
  50. package/dist/{registerKillSessionHandler-CfCya6si.cjs → sessionControl-flKnQrx0.cjs} +1647 -2417
  51. package/dist/{api-DnqaNvyV.mjs → types-B5vtxa38.mjs} +55 -5
  52. package/dist/{api-D7nAeZi7.cjs → types-CttABk32.cjs} +55 -4
  53. package/package.json +2 -2
  54. package/dist/types-CiliQpqS.mjs +0 -52
  55. package/dist/types-DVk3crez.cjs +0 -54
@@ -0,0 +1,577 @@
1
+ import { A as AcpBackend } from './AcpBackend-CqO3D07V.mjs';
2
+ import { a as agentRegistry } from './RuntimeShell-BDt42io_.mjs';
3
+ import { l as logger } from './types-B5vtxa38.mjs';
4
+ import { p as projectPath, C as CodexTransport } from './index-CX-F_fuk.mjs';
5
+ import { r as resolveCommandOnPath, a as resolveCodexAcpSpawn } from './resolveCommand-B3BGyBE2.mjs';
6
+ import fs, { mkdtempSync, mkdirSync, rmSync, readFileSync, existsSync, readdirSync, cpSync, statSync, realpathSync } from 'node:fs';
7
+ import os, { homedir, tmpdir } from 'node:os';
8
+ import path, { join, relative, isAbsolute, normalize, dirname, basename } from 'node:path';
9
+
10
+ function firstExistingPath(candidates) {
11
+ for (const candidate of candidates) {
12
+ try {
13
+ if (fs.existsSync(candidate)) {
14
+ return candidate;
15
+ }
16
+ } catch {
17
+ }
18
+ }
19
+ return null;
20
+ }
21
+ function resolveCodexExecutable() {
22
+ if (process.platform === "win32") {
23
+ const appData = process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
24
+ const npmGlobalBin = path.join(appData, "npm");
25
+ const resolved = firstExistingPath([
26
+ path.join(npmGlobalBin, "codex.cmd"),
27
+ path.join(npmGlobalBin, "codex.ps1"),
28
+ path.join(npmGlobalBin, "codex")
29
+ ]);
30
+ if (resolved) {
31
+ return resolved;
32
+ }
33
+ }
34
+ return "codex";
35
+ }
36
+ function shouldUseShellForCodex(executable) {
37
+ return process.platform === "win32" && /\.(cmd|bat|ps1)$/i.test(executable);
38
+ }
39
+
40
+ const CODEX_HOME_SEED_FILES = [
41
+ "auth.json",
42
+ "config.toml",
43
+ "cap_sid",
44
+ "version.json",
45
+ "MEMORY.md"
46
+ ];
47
+ const CODEX_HOME_SEED_DIRS = [
48
+ "rules"
49
+ ];
50
+ const MAX_CODEX_SKILL_DESCRIPTION_LENGTH = 1024;
51
+ const MANAGED_CODEX_HOME_PREFIX = "happy-codex-home-";
52
+ function isPlainObject(value) {
53
+ return typeof value === "object" && value !== null && !Array.isArray(value);
54
+ }
55
+ function isApiKeyOnlyCodexAuth(value) {
56
+ if (!isPlainObject(value)) {
57
+ return false;
58
+ }
59
+ const entries = Object.entries(value).filter(([, entryValue]) => entryValue !== void 0 && entryValue !== null);
60
+ return entries.length === 1 && typeof value.OPENAI_API_KEY === "string" && value.OPENAI_API_KEY.trim().length > 0;
61
+ }
62
+ function shouldUseSourceCodexHomeForMutableAuth(sourceHomeDir) {
63
+ try {
64
+ const auth = JSON.parse(readFileSync(join(sourceHomeDir, "auth.json"), "utf8"));
65
+ return !isApiKeyOnlyCodexAuth(auth);
66
+ } catch {
67
+ return false;
68
+ }
69
+ }
70
+ function getCodexPlatformTarget(platform, arch) {
71
+ if (platform === "win32" && arch === "x64") {
72
+ return {
73
+ packageName: "codex-win32-x64",
74
+ targetTriple: "x86_64-pc-windows-msvc"
75
+ };
76
+ }
77
+ if (platform === "win32" && arch === "arm64") {
78
+ return {
79
+ packageName: "codex-win32-arm64",
80
+ targetTriple: "aarch64-pc-windows-msvc"
81
+ };
82
+ }
83
+ if ((platform === "linux" || platform === "android") && arch === "x64") {
84
+ return {
85
+ packageName: "codex-linux-x64",
86
+ targetTriple: "x86_64-unknown-linux-musl"
87
+ };
88
+ }
89
+ if ((platform === "linux" || platform === "android") && arch === "arm64") {
90
+ return {
91
+ packageName: "codex-linux-arm64",
92
+ targetTriple: "aarch64-unknown-linux-musl"
93
+ };
94
+ }
95
+ if (platform === "darwin" && arch === "x64") {
96
+ return {
97
+ packageName: "codex-darwin-x64",
98
+ targetTriple: "x86_64-apple-darwin"
99
+ };
100
+ }
101
+ if (platform === "darwin" && arch === "arm64") {
102
+ return {
103
+ packageName: "codex-darwin-arm64",
104
+ targetTriple: "aarch64-apple-darwin"
105
+ };
106
+ }
107
+ return null;
108
+ }
109
+ function dedupePaths(paths, platform) {
110
+ const seen = /* @__PURE__ */ new Set();
111
+ const unique = [];
112
+ for (const entry of paths) {
113
+ const normalized = normalize(entry);
114
+ const key = platform === "win32" ? normalized.toLowerCase() : normalized;
115
+ if (seen.has(key)) {
116
+ continue;
117
+ }
118
+ seen.add(key);
119
+ unique.push(entry);
120
+ }
121
+ return unique;
122
+ }
123
+ function getPathDelimiter(platform) {
124
+ return platform === "win32" ? ";" : ":";
125
+ }
126
+ function resolveCodexShimPath({
127
+ platform = process.platform,
128
+ exists = existsSync,
129
+ resolveExecutable = resolveCodexExecutable,
130
+ resolveOnPath = resolveCommandOnPath
131
+ }) {
132
+ const resolvedExecutable = resolveExecutable();
133
+ if (isAbsolute(resolvedExecutable) && exists(resolvedExecutable)) {
134
+ return resolvedExecutable;
135
+ }
136
+ const commandNames = platform === "win32" ? ["codex.cmd", "codex.ps1", "codex"] : ["codex"];
137
+ for (const commandName of commandNames) {
138
+ const resolved = resolveOnPath(commandName);
139
+ if (resolved) {
140
+ return resolved;
141
+ }
142
+ }
143
+ return null;
144
+ }
145
+ function resolveCodexPackageRoots(executablePath, {
146
+ platform = process.platform,
147
+ exists = existsSync,
148
+ realpath = realpathSync
149
+ }) {
150
+ const executableDir = dirname(executablePath);
151
+ const candidates = [
152
+ join(executableDir, "node_modules", "@openai", "codex"),
153
+ join(executableDir, "..", "lib", "node_modules", "@openai", "codex")
154
+ ];
155
+ try {
156
+ const realExecutablePath = realpath(executablePath);
157
+ candidates.push(join(dirname(realExecutablePath), ".."));
158
+ } catch {
159
+ }
160
+ return dedupePaths(
161
+ candidates.filter((candidate) => exists(candidate)),
162
+ platform
163
+ );
164
+ }
165
+ function resolvePathEnvKey(env) {
166
+ return Object.prototype.hasOwnProperty.call(env, "Path") && !Object.prototype.hasOwnProperty.call(env, "PATH") ? "Path" : "PATH";
167
+ }
168
+ function resolveBundledCodexToolPathDirs(options = {}) {
169
+ const platform = options.platform ?? process.platform;
170
+ const arch = options.arch ?? process.arch;
171
+ const codexTarget = getCodexPlatformTarget(platform, arch);
172
+ if (!codexTarget) {
173
+ return [];
174
+ }
175
+ const codexShimPath = resolveCodexShimPath(options);
176
+ if (!codexShimPath) {
177
+ return [];
178
+ }
179
+ const packageRoots = resolveCodexPackageRoots(codexShimPath, options);
180
+ if (packageRoots.length === 0) {
181
+ return [];
182
+ }
183
+ const exists = options.exists ?? existsSync;
184
+ const candidates = packageRoots.flatMap((packageRoot) => [
185
+ join(packageRoot, "vendor", codexTarget.targetTriple, "path"),
186
+ join(
187
+ packageRoot,
188
+ "node_modules",
189
+ "@openai",
190
+ codexTarget.packageName,
191
+ "vendor",
192
+ codexTarget.targetTriple,
193
+ "path"
194
+ )
195
+ ]);
196
+ return dedupePaths(
197
+ candidates.filter((candidate) => exists(candidate)),
198
+ platform
199
+ );
200
+ }
201
+ function buildCodexAcpEnv(overrides = {}, options = {}) {
202
+ const platform = options.platform ?? process.platform;
203
+ const pathDelimiter = getPathDelimiter(platform);
204
+ const env = {
205
+ ...process.env,
206
+ ...overrides
207
+ };
208
+ const pathKey = resolvePathEnvKey(env);
209
+ const alternatePathKey = pathKey === "PATH" ? "Path" : "PATH";
210
+ const currentPathValue = env[pathKey] ?? env[alternatePathKey] ?? "";
211
+ const currentPathEntries = currentPathValue.split(pathDelimiter).filter(Boolean);
212
+ const codexToolDirs = resolveBundledCodexToolPathDirs(options);
213
+ const mergedPathEntries = dedupePaths(
214
+ [...codexToolDirs, ...currentPathEntries],
215
+ platform
216
+ );
217
+ if (mergedPathEntries.length > 0) {
218
+ env[pathKey] = mergedPathEntries.join(pathDelimiter);
219
+ }
220
+ delete env[alternatePathKey];
221
+ const stringEnvEntries = [];
222
+ for (const [key, value] of Object.entries(env)) {
223
+ if (typeof value === "string") {
224
+ stringEnvEntries.push([key, value]);
225
+ }
226
+ }
227
+ return Object.fromEntries(stringEnvEntries);
228
+ }
229
+ function copyCodexHomeEntry(sourcePath, destPath) {
230
+ if (!existsSync(sourcePath)) {
231
+ return;
232
+ }
233
+ mkdirSync(dirname(destPath), { recursive: true });
234
+ cpSync(sourcePath, destPath, {
235
+ recursive: true,
236
+ force: true,
237
+ dereference: false,
238
+ verbatimSymlinks: true
239
+ });
240
+ }
241
+ function normalizePathForComparison(path, platform) {
242
+ const normalizedPath = normalize(path).replace(/[\\/]+/g, "/").replace(/\/+$/, "");
243
+ return platform === "win32" ? normalizedPath.toLowerCase() : normalizedPath;
244
+ }
245
+ function isManagedTemporaryCodexHomePath(path, platform) {
246
+ const trimmedPath = path.trim();
247
+ if (!trimmedPath) {
248
+ return false;
249
+ }
250
+ const pathBaseName = trimmedPath.replace(/[\\/]+$/, "").split(/[\\/]/).at(-1) ?? "";
251
+ if (!pathBaseName.startsWith(MANAGED_CODEX_HOME_PREFIX)) {
252
+ return false;
253
+ }
254
+ const normalizedTempRoot = normalizePathForComparison(tmpdir(), platform);
255
+ const normalizedPath = normalizePathForComparison(trimmedPath, platform);
256
+ return normalizedPath.startsWith(`${normalizedTempRoot}/`);
257
+ }
258
+ function extractSkillDescriptionFromFrontmatter(frontmatter) {
259
+ const lines = frontmatter.split(/\r?\n/);
260
+ for (let index = 0; index < lines.length; index++) {
261
+ const line = lines[index];
262
+ const match = /^description:\s*(.*)$/.exec(line);
263
+ if (!match) {
264
+ continue;
265
+ }
266
+ const remainder = match[1]?.trim() ?? "";
267
+ if (!remainder || remainder === "|" || remainder === ">") {
268
+ const descriptionLines = [];
269
+ for (let offset = index + 1; offset < lines.length; offset++) {
270
+ const descriptionLine = lines[offset] ?? "";
271
+ if (descriptionLine.length > 0 && !/^\s/.test(descriptionLine)) {
272
+ break;
273
+ }
274
+ descriptionLines.push(descriptionLine.replace(/^\s{2}/, ""));
275
+ }
276
+ return descriptionLines.join("\n").trim();
277
+ }
278
+ return remainder.replace(/^['"]|['"]$/g, "").trim();
279
+ }
280
+ return null;
281
+ }
282
+ function extractSkillDescription(skillManifestPath) {
283
+ const manifest = readFileSync(skillManifestPath, "utf8");
284
+ const frontmatterMatch = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(manifest);
285
+ const frontmatter = frontmatterMatch?.[1];
286
+ if (!frontmatter) {
287
+ return null;
288
+ }
289
+ return extractSkillDescriptionFromFrontmatter(frontmatter);
290
+ }
291
+ function shouldSeedCodexSkillEntry(sourcePath) {
292
+ if (basename(sourcePath) === ".system") {
293
+ return true;
294
+ }
295
+ const manifestPath = join(sourcePath, "SKILL.md");
296
+ if (!existsSync(manifestPath)) {
297
+ return true;
298
+ }
299
+ try {
300
+ const description = extractSkillDescription(manifestPath);
301
+ if (description && description.length > MAX_CODEX_SKILL_DESCRIPTION_LENGTH) {
302
+ logger.debug(
303
+ `[codex] Skipping CODEX_HOME skill entry ${sourcePath} because its description exceeds ${MAX_CODEX_SKILL_DESCRIPTION_LENGTH} characters`
304
+ );
305
+ return false;
306
+ }
307
+ } catch (error) {
308
+ logger.debug(`[codex] Failed to inspect CODEX_HOME skill entry ${sourcePath}`, error);
309
+ }
310
+ return true;
311
+ }
312
+ function seedCodexSkillEntries(sourceSkillsDir, isolatedHomeDir, sourceLabel) {
313
+ if (!existsSync(sourceSkillsDir)) {
314
+ return;
315
+ }
316
+ const destSkillsDir = join(isolatedHomeDir, "skills");
317
+ mkdirSync(destSkillsDir, { recursive: true });
318
+ for (const entryName of readdirSync(sourceSkillsDir)) {
319
+ const sourceEntryPath = join(sourceSkillsDir, entryName);
320
+ if (!shouldSeedCodexSkillEntry(sourceEntryPath)) {
321
+ continue;
322
+ }
323
+ try {
324
+ copyCodexHomeEntry(
325
+ sourceEntryPath,
326
+ join(destSkillsDir, entryName)
327
+ );
328
+ } catch (error) {
329
+ logger.debug(`[codex] Failed to seed CODEX_HOME skills entry ${entryName} from ${sourceLabel}`, error);
330
+ }
331
+ }
332
+ }
333
+ function isWithinDirectory(parentDir, childPath, platform) {
334
+ const normalizedParent = normalizePathForComparison(parentDir, platform);
335
+ const normalizedChild = normalizePathForComparison(childPath, platform);
336
+ return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}/`);
337
+ }
338
+ function extractCodexSessionIdFromFilePath(filePath) {
339
+ 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$/);
340
+ return match?.[1] ?? null;
341
+ }
342
+ function findCodexSessionFile(sourceHomeDir, resumeSessionId, platform) {
343
+ const sessionsRoot = join(sourceHomeDir, "sessions");
344
+ const stack = [sessionsRoot];
345
+ let bestMatch = null;
346
+ while (stack.length > 0) {
347
+ const currentDir = stack.pop();
348
+ let entries;
349
+ try {
350
+ entries = readdirSync(currentDir, { withFileTypes: true });
351
+ } catch {
352
+ continue;
353
+ }
354
+ for (const entry of entries) {
355
+ const fullPath = join(currentDir, entry.name);
356
+ if (!isWithinDirectory(sessionsRoot, fullPath, platform)) {
357
+ continue;
358
+ }
359
+ if (entry.isDirectory()) {
360
+ stack.push(fullPath);
361
+ continue;
362
+ }
363
+ if (!entry.isFile() || extractCodexSessionIdFromFilePath(fullPath) !== resumeSessionId) {
364
+ continue;
365
+ }
366
+ try {
367
+ const mtimeMs = statSync(fullPath).mtimeMs;
368
+ if (!bestMatch || mtimeMs > bestMatch.mtimeMs) {
369
+ bestMatch = { path: fullPath, mtimeMs };
370
+ }
371
+ } catch {
372
+ }
373
+ }
374
+ }
375
+ return bestMatch?.path ?? null;
376
+ }
377
+ function seedCodexResumeSessionFile(sourceHomeDir, isolatedHomeDir, resumeSessionId, platform) {
378
+ const normalizedResumeSessionId = typeof resumeSessionId === "string" && resumeSessionId.trim() ? resumeSessionId.trim() : null;
379
+ if (!normalizedResumeSessionId) {
380
+ return;
381
+ }
382
+ const sourceSessionFile = findCodexSessionFile(sourceHomeDir, normalizedResumeSessionId, platform);
383
+ if (!sourceSessionFile) {
384
+ logger.debug(`[codex] No source CODEX_HOME session file found for resume id ${normalizedResumeSessionId}`);
385
+ return;
386
+ }
387
+ const sourceSessionsRoot = join(sourceHomeDir, "sessions");
388
+ const relativeSessionPath = relative(sourceSessionsRoot, sourceSessionFile);
389
+ if (!relativeSessionPath || relativeSessionPath.startsWith("..") || isAbsolute(relativeSessionPath)) {
390
+ logger.debug(`[codex] Refusing to seed CODEX_HOME session outside sessions root: ${sourceSessionFile}`);
391
+ return;
392
+ }
393
+ try {
394
+ copyCodexHomeEntry(
395
+ sourceSessionFile,
396
+ join(isolatedHomeDir, "sessions", relativeSessionPath)
397
+ );
398
+ } catch (error) {
399
+ logger.debug(`[codex] Failed to seed CODEX_HOME session file for ${normalizedResumeSessionId}`, error);
400
+ }
401
+ }
402
+ function shouldSyncCodexSessionFileBack(sourcePath, destPath) {
403
+ let sourceStat;
404
+ try {
405
+ sourceStat = statSync(sourcePath);
406
+ } catch {
407
+ return false;
408
+ }
409
+ if (!sourceStat.isFile()) {
410
+ return false;
411
+ }
412
+ let destStat;
413
+ try {
414
+ destStat = statSync(destPath);
415
+ } catch {
416
+ return true;
417
+ }
418
+ return sourceStat.mtimeMs >= destStat.mtimeMs || sourceStat.size !== destStat.size;
419
+ }
420
+ function syncCodexSessionFilesBackToSource(isolatedHomeDir, sourceHomeDir, platform) {
421
+ const isolatedSessionsRoot = join(isolatedHomeDir, "sessions");
422
+ const sourceSessionsRoot = join(sourceHomeDir, "sessions");
423
+ const stack = [isolatedSessionsRoot];
424
+ while (stack.length > 0) {
425
+ const currentDir = stack.pop();
426
+ let entries;
427
+ try {
428
+ entries = readdirSync(currentDir, { withFileTypes: true });
429
+ } catch {
430
+ continue;
431
+ }
432
+ for (const entry of entries) {
433
+ const fullPath = join(currentDir, entry.name);
434
+ if (!isWithinDirectory(isolatedSessionsRoot, fullPath, platform)) {
435
+ continue;
436
+ }
437
+ if (entry.isDirectory()) {
438
+ stack.push(fullPath);
439
+ continue;
440
+ }
441
+ if (!entry.isFile() || extractCodexSessionIdFromFilePath(fullPath) === null) {
442
+ continue;
443
+ }
444
+ const relativeSessionPath = relative(isolatedSessionsRoot, fullPath);
445
+ if (!relativeSessionPath || relativeSessionPath.startsWith("..") || isAbsolute(relativeSessionPath)) {
446
+ logger.debug(`[codex] Refusing to sync CODEX_HOME session outside sessions root: ${fullPath}`);
447
+ continue;
448
+ }
449
+ const destPath = join(sourceSessionsRoot, relativeSessionPath);
450
+ if (!shouldSyncCodexSessionFileBack(fullPath, destPath)) {
451
+ continue;
452
+ }
453
+ try {
454
+ copyCodexHomeEntry(fullPath, destPath);
455
+ } catch (error) {
456
+ logger.debug(`[codex] Failed to sync CODEX_HOME session file back to source: ${fullPath}`, error);
457
+ }
458
+ }
459
+ }
460
+ }
461
+ function seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir, resumeSessionId, platform) {
462
+ if (existsSync(sourceHomeDir)) {
463
+ for (const fileName of CODEX_HOME_SEED_FILES) {
464
+ try {
465
+ copyCodexHomeEntry(join(sourceHomeDir, fileName), join(isolatedHomeDir, fileName));
466
+ } catch (error) {
467
+ logger.debug(`[codex] Failed to seed CODEX_HOME file ${fileName}`, error);
468
+ }
469
+ }
470
+ for (const dirName of CODEX_HOME_SEED_DIRS) {
471
+ try {
472
+ copyCodexHomeEntry(join(sourceHomeDir, dirName), join(isolatedHomeDir, dirName));
473
+ } catch (error) {
474
+ logger.debug(`[codex] Failed to seed CODEX_HOME directory ${dirName}`, error);
475
+ }
476
+ }
477
+ }
478
+ if (bundledSkillsDir) {
479
+ seedCodexSkillEntries(bundledSkillsDir, isolatedHomeDir, "bundled skills");
480
+ }
481
+ seedCodexSkillEntries(join(sourceHomeDir, "skills"), isolatedHomeDir, "source CODEX_HOME");
482
+ seedCodexResumeSessionFile(sourceHomeDir, isolatedHomeDir, resumeSessionId, platform);
483
+ }
484
+ function prepareCodexAcpEnvironment(overrides = {}, options = {}) {
485
+ const env = buildCodexAcpEnv(overrides, options);
486
+ const platform = options.platform ?? process.platform;
487
+ if (platform !== "win32") {
488
+ return { env };
489
+ }
490
+ const explicitCodexHome = typeof overrides.CODEX_HOME === "string" ? overrides.CODEX_HOME.trim() : "";
491
+ const existingCodexHome = typeof env.CODEX_HOME === "string" ? env.CODEX_HOME.trim() : "";
492
+ if (existingCodexHome) {
493
+ if (!explicitCodexHome && isManagedTemporaryCodexHomePath(existingCodexHome, platform)) {
494
+ logger.debug(`[codex] Ignoring inherited managed CODEX_HOME ${existingCodexHome} and rebuilding an isolated home`);
495
+ delete env.CODEX_HOME;
496
+ } else {
497
+ return { env };
498
+ }
499
+ }
500
+ const sourceHomeDir = options.sourceHomeDir ?? join(homedir(), ".codex");
501
+ const bundledSkillsDir = options.bundledSkillsDir ?? join(projectPath(), "skills");
502
+ if (shouldUseSourceCodexHomeForMutableAuth(sourceHomeDir)) {
503
+ logger.debug("[codex] Using source CODEX_HOME for mutable Codex auth credentials");
504
+ env.CODEX_HOME = sourceHomeDir;
505
+ return {
506
+ env,
507
+ codexHomePath: sourceHomeDir
508
+ };
509
+ }
510
+ const tempDirFactory = options.tempDirFactory ?? mkdtempSync;
511
+ const isolatedHomeDir = tempDirFactory(join(tmpdir(), "happy-codex-home-"));
512
+ mkdirSync(isolatedHomeDir, { recursive: true });
513
+ seedIsolatedCodexHome(sourceHomeDir, isolatedHomeDir, bundledSkillsDir, options.resumeSessionId, platform);
514
+ env.CODEX_HOME = isolatedHomeDir;
515
+ return {
516
+ env,
517
+ codexHomePath: isolatedHomeDir,
518
+ cleanup: () => {
519
+ syncCodexSessionFilesBackToSource(isolatedHomeDir, sourceHomeDir, platform);
520
+ rmSync(isolatedHomeDir, { recursive: true, force: true });
521
+ }
522
+ };
523
+ }
524
+
525
+ class CodexAcpTransport extends CodexTransport {
526
+ constructor(initTimeoutMs) {
527
+ super();
528
+ this.initTimeoutMs = initTimeoutMs;
529
+ }
530
+ getInitTimeout() {
531
+ return this.initTimeoutMs;
532
+ }
533
+ }
534
+ function resolveCodexTransport(command) {
535
+ if (/npx(?:\.cmd)?$/i.test(command)) {
536
+ return new CodexAcpTransport(18e4);
537
+ }
538
+ return new CodexAcpTransport(6e4);
539
+ }
540
+ function createCodexBackend(options) {
541
+ const spawn = resolveCodexAcpSpawn({
542
+ command: options.command,
543
+ args: options.args,
544
+ baseArgs: options.baseArgs,
545
+ model: options.model,
546
+ sandbox: options.sandbox,
547
+ approvalPolicy: options.approvalPolicy
548
+ });
549
+ const preparedEnv = prepareCodexAcpEnvironment({
550
+ ...options.env,
551
+ NODE_ENV: "production"
552
+ }, {
553
+ resumeSessionId: options.resumeSessionId
554
+ });
555
+ const backendOptions = {
556
+ agentName: "codex",
557
+ cwd: options.cwd,
558
+ command: spawn.command,
559
+ args: spawn.args,
560
+ env: preparedEnv.env,
561
+ permissionHandler: options.permissionHandler,
562
+ selectionHandler: options.selectionHandler,
563
+ transportHandler: resolveCodexTransport(spawn.command),
564
+ resourceCleanup: preparedEnv.cleanup,
565
+ resumeSessionId: options.resumeSessionId
566
+ };
567
+ return {
568
+ backend: new AcpBackend(backendOptions),
569
+ command: spawn.command,
570
+ args: spawn.args
571
+ };
572
+ }
573
+ function registerCodexAgent() {
574
+ agentRegistry.register("codex", (opts) => createCodexBackend(opts).backend);
575
+ }
576
+
577
+ export { resolveCodexExecutable as a, createCodexBackend as c, registerCodexAgent as r, shouldUseShellForCodex as s };