@episoda/cli 0.2.214 → 0.2.216

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.
@@ -3051,10 +3051,17 @@ var require_package = __commonJS({
3051
3051
  "package.json"(exports2, module2) {
3052
3052
  module2.exports = {
3053
3053
  name: "@episoda/cli",
3054
- version: "0.2.214",
3054
+ version: "0.2.216",
3055
3055
  description: "CLI tool for Episoda local development workflow orchestration",
3056
3056
  main: "dist/index.js",
3057
3057
  types: "dist/index.d.ts",
3058
+ exports: {
3059
+ ".": {
3060
+ types: "./dist/index.d.ts",
3061
+ require: "./dist/index.js",
3062
+ default: "./dist/index.js"
3063
+ }
3064
+ },
3058
3065
  bin: {
3059
3066
  episoda: "dist/index.js"
3060
3067
  },
@@ -4797,6 +4804,93 @@ async function ensureCodexBinary() {
4797
4804
 
4798
4805
  // src/agent/providers/codex-config.ts
4799
4806
  var DEFAULT_CODEX_MODEL = "gpt-5.4";
4807
+ var SUPPORTED_CODEX_PTY_MODELS = ["gpt-5.4", "gpt-5.3-codex"];
4808
+ function stripUnsupportedCodexFlags(args) {
4809
+ const sanitized = [];
4810
+ for (let index = 0; index < args.length; index += 1) {
4811
+ const current = args[index];
4812
+ if (current === "--effort") {
4813
+ index += 1;
4814
+ continue;
4815
+ }
4816
+ if (current.startsWith("--effort=")) {
4817
+ continue;
4818
+ }
4819
+ sanitized.push(current);
4820
+ }
4821
+ return sanitized;
4822
+ }
4823
+ function extractRequestedModel(args) {
4824
+ for (let index = 0; index < args.length; index += 1) {
4825
+ if (args[index] === "--model") {
4826
+ const candidate = args[index + 1];
4827
+ return typeof candidate === "string" && candidate.trim().length > 0 ? candidate.trim() : null;
4828
+ }
4829
+ }
4830
+ return null;
4831
+ }
4832
+ function resolveSupportedCodexModel(model) {
4833
+ const normalized = (model || "").trim();
4834
+ if (SUPPORTED_CODEX_PTY_MODELS.includes(normalized)) {
4835
+ return normalized;
4836
+ }
4837
+ if (normalized.toLowerCase().endsWith("-high")) {
4838
+ return DEFAULT_CODEX_MODEL;
4839
+ }
4840
+ return DEFAULT_CODEX_MODEL;
4841
+ }
4842
+ function upsertModelArg(args, model) {
4843
+ const nextArgs = [...args];
4844
+ for (let index = 0; index < nextArgs.length; index += 1) {
4845
+ if (nextArgs[index] === "--model") {
4846
+ if (index + 1 < nextArgs.length) {
4847
+ nextArgs[index + 1] = model;
4848
+ return nextArgs;
4849
+ }
4850
+ nextArgs.push(model);
4851
+ return nextArgs;
4852
+ }
4853
+ }
4854
+ if (nextArgs[0] === "exec") {
4855
+ return ["exec", "--model", model, ...nextArgs.slice(1)];
4856
+ }
4857
+ return ["--model", model, ...nextArgs];
4858
+ }
4859
+ function resolveCodexExecutionConfig(options) {
4860
+ const requestedModel = options.preferredModel || extractRequestedModel(options.args || []);
4861
+ const model = resolveSupportedCodexModel(requestedModel);
4862
+ const env = { ...options.env || {} };
4863
+ if (Array.isArray(options.args) && options.args.length > 0) {
4864
+ return {
4865
+ model,
4866
+ args: upsertModelArg(stripUnsupportedCodexFlags(options.args), model),
4867
+ env
4868
+ };
4869
+ }
4870
+ const runType = options.runType || "persistent";
4871
+ const prompt = options.prompt || "";
4872
+ const useYolo = options.useYolo !== false;
4873
+ const effortArgs = options.effort ? ["-c", `reasoning_effort="${options.effort}"`] : [];
4874
+ if (runType === "persistent") {
4875
+ return {
4876
+ model,
4877
+ args: ["--model", model, "--yolo", "--sandbox", "danger-full-access"],
4878
+ env
4879
+ };
4880
+ }
4881
+ if (useYolo) {
4882
+ return {
4883
+ model,
4884
+ args: ["--model", model, ...effortArgs, "--yolo", "--sandbox", "danger-full-access", prompt],
4885
+ env
4886
+ };
4887
+ }
4888
+ return {
4889
+ model,
4890
+ args: ["exec", "--json", "--model", model, ...effortArgs, "--sandbox", "danger-full-access", "--skip-git-repo-check", prompt],
4891
+ env
4892
+ };
4893
+ }
4800
4894
  function generateCodexAuthJson(credentials) {
4801
4895
  const tokens = {
4802
4896
  id_token: credentials.idToken || credentials.accessToken,
@@ -12984,8 +13078,10 @@ var fs31 = __toESM(require("fs"));
12984
13078
  var os14 = __toESM(require("os"));
12985
13079
  var path31 = __toESM(require("path"));
12986
13080
  var INACTIVITY_TIMEOUT_MS3 = 30 * 60 * 1e3;
12987
- var CODEX_READINESS_SIGNAL = /(?:\d+% left ·|\bmodel:\s+gpt-)/i;
12988
13081
  var ANSI_ESCAPE_CODE_REGEX = /\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g;
13082
+ var CODEX_BANNER_SIGNAL = /(openai codex|\bmodel:)/i;
13083
+ var CODEX_PROMPT_SIGNAL = /(?:^|\n)\s*(?:>|❯)\s*$/m;
13084
+ var MAX_CODEX_STARTUP_READY_TIMEOUT_MS = 3e4;
12989
13085
  var sessions = /* @__PURE__ */ new Map();
12990
13086
  function killPtySessionsForModule(moduleUid) {
12991
13087
  const killedRunIds = [];
@@ -13024,16 +13120,30 @@ async function handlePtySpawn(payload, client) {
13024
13120
  console.log(`[PTY] Spawning PTY for ${moduleUid} / ${agent_run_id}: ${command} ${args.join(" ")}`);
13025
13121
  let bootstrap = null;
13026
13122
  let proc;
13123
+ let modelUsed;
13124
+ let launchConfig;
13125
+ let spawnArgs = args;
13027
13126
  try {
13028
13127
  bootstrap = createCredentialBootstrap(payload, agent_run_id);
13029
- proc = pty.spawn(command, args, {
13128
+ const executionConfig = command === "codex" ? resolveCodexExecutionConfig({ args, env }) : null;
13129
+ spawnArgs = executionConfig?.args ?? args;
13130
+ const spawnEnv = executionConfig?.env ?? (env || {});
13131
+ modelUsed = executionConfig?.model;
13132
+ launchConfig = buildPtyLaunchConfig({
13133
+ command,
13134
+ args: spawnArgs,
13135
+ env: spawnEnv,
13136
+ cwd: cwd || process.cwd(),
13137
+ bootstrap
13138
+ });
13139
+ proc = pty.spawn(command, spawnArgs, {
13030
13140
  name: "xterm-256color",
13031
13141
  cols,
13032
13142
  rows,
13033
13143
  cwd: cwd || process.cwd(),
13034
13144
  env: {
13035
13145
  ...process.env,
13036
- ...env || {},
13146
+ ...spawnEnv,
13037
13147
  ...bootstrap.env
13038
13148
  }
13039
13149
  });
@@ -13051,7 +13161,10 @@ async function handlePtySpawn(payload, client) {
13051
13161
  });
13052
13162
  return {
13053
13163
  success: false,
13054
- error: err?.message || `Failed to spawn PTY command '${command}'`
13164
+ error: err?.message || `Failed to spawn PTY command '${command}'`,
13165
+ modelUsed,
13166
+ launchConfig,
13167
+ authPath: bootstrap?.authPath
13055
13168
  };
13056
13169
  }
13057
13170
  const session = {
@@ -13063,7 +13176,7 @@ async function handlePtySpawn(payload, client) {
13063
13176
  lastOutputAt: Date.now(),
13064
13177
  watchdogTimer: null,
13065
13178
  credentialDirs: bootstrap.cleanupDirs,
13066
- startup: createStartupState(payload)
13179
+ startup: createStartupState(payload, spawnArgs)
13067
13180
  };
13068
13181
  sessions.set(agent_run_id, session);
13069
13182
  const resetWatchdog = () => {
@@ -13080,7 +13193,7 @@ async function handlePtySpawn(payload, client) {
13080
13193
  resetWatchdog();
13081
13194
  proc.onData((data) => {
13082
13195
  resetWatchdog();
13083
- maybeSeedBufferedInitialPrompt(session, data);
13196
+ handleStartupData(session, data);
13084
13197
  client.send({
13085
13198
  type: "pty_data",
13086
13199
  moduleUid,
@@ -13096,7 +13209,8 @@ async function handlePtySpawn(payload, client) {
13096
13209
  proc.onExit(({ exitCode }) => {
13097
13210
  if (session.startup && !session.startup.readinessObserved) {
13098
13211
  session.startup.markFailed(
13099
- `Codex PTY exited before startup readiness for ${agent_run_id} (exit code ${exitCode}).`
13212
+ `Codex PTY exited before startup readiness for ${agent_run_id} (exit code ${exitCode}).`,
13213
+ session.startup.failureClass || "EXIT_BEFORE_READY"
13100
13214
  );
13101
13215
  }
13102
13216
  const durationMs = Date.now() - session.startedAt;
@@ -13121,11 +13235,22 @@ async function handlePtySpawn(payload, client) {
13121
13235
  } catch (error) {
13122
13236
  return {
13123
13237
  success: false,
13124
- error: error?.message || "Codex PTY failed before startup readiness"
13238
+ error: error?.message || "Codex PTY failed before startup readiness",
13239
+ startupFailureClass: session.startup.failureClass,
13240
+ startupConfirmedAt: session.startup.startupConfirmedAt,
13241
+ modelUsed,
13242
+ launchConfig,
13243
+ authPath: bootstrap.authPath
13125
13244
  };
13126
13245
  }
13127
13246
  }
13128
- return { success: true };
13247
+ return {
13248
+ success: true,
13249
+ startupConfirmedAt: session.startup?.startupConfirmedAt,
13250
+ modelUsed,
13251
+ launchConfig,
13252
+ authPath: bootstrap.authPath
13253
+ };
13129
13254
  }
13130
13255
  function handlePtyResize(payload) {
13131
13256
  const { agent_run_id, cols, rows } = payload;
@@ -13200,29 +13325,40 @@ function createCredentialBootstrap(payload, agentRunId) {
13200
13325
  fs31.writeFileSync(credentialsPath, JSON.stringify({ claudeAiOauth }, null, 2), { mode: 384 });
13201
13326
  return {
13202
13327
  env: { CLAUDE_CONFIG_DIR: claudeConfigDir },
13203
- cleanupDirs
13328
+ cleanupDirs,
13329
+ authPath: credentialsPath
13204
13330
  };
13205
13331
  }
13206
13332
  const codexHome = path31.join(baseDir, ".codex");
13207
13333
  fs31.mkdirSync(codexHome, { recursive: true });
13334
+ const trustedProjectRoot = resolveCodexTrustedProjectRoot(payload);
13208
13335
  const configFiles = generateCodexConfig({
13209
13336
  accessToken: bootstrap.oauth.access_token,
13210
13337
  idToken: bootstrap.oauth.id_token,
13211
13338
  accountId: bootstrap.oauth.account_id
13212
- }, payload.cwd);
13213
- fs31.writeFileSync(path31.join(codexHome, "auth.json"), configFiles["auth.json"], { mode: 384 });
13339
+ }, trustedProjectRoot);
13340
+ const authPath = path31.join(codexHome, "auth.json");
13341
+ const configPath = path31.join(codexHome, "config.toml");
13342
+ fs31.writeFileSync(authPath, configFiles["auth.json"], { mode: 384 });
13214
13343
  if (configFiles["config.toml"]) {
13215
- fs31.writeFileSync(path31.join(codexHome, "config.toml"), configFiles["config.toml"], { mode: 384 });
13344
+ fs31.writeFileSync(configPath, configFiles["config.toml"], { mode: 384 });
13216
13345
  }
13217
13346
  return {
13218
13347
  env: { CODEX_HOME: codexHome },
13219
- cleanupDirs
13348
+ cleanupDirs,
13349
+ authPath,
13350
+ configPath,
13351
+ codexHome,
13352
+ trustedProjectRoot
13220
13353
  };
13221
13354
  }
13222
- function createStartupState(payload) {
13223
- if (payload.run_type !== "persistent" || payload.command !== "codex" || typeof payload.stdin !== "string" || payload.stdin.trim().length === 0) {
13355
+ function createStartupState(payload, resolvedArgs) {
13356
+ if (payload.command !== "codex") {
13224
13357
  return void 0;
13225
13358
  }
13359
+ const trimmedStdin = typeof payload.stdin === "string" ? payload.stdin.trim() : "";
13360
+ const trimmedArgvPrompt = payload.run_type === "persistent" ? "" : resolveCodexArgvPrompt(resolvedArgs);
13361
+ const mode = payload.run_type === "persistent" ? trimmedStdin.length > 0 ? "seed_after_prompt" : "prompt_ready" : "first_output";
13226
13362
  let resolveReady;
13227
13363
  let rejectReady;
13228
13364
  const waitForReady = new Promise((resolve9, reject) => {
@@ -13230,10 +13366,14 @@ function createStartupState(payload) {
13230
13366
  rejectReady = reject;
13231
13367
  });
13232
13368
  const startup = {
13233
- pendingInitialStdin: payload.stdin,
13369
+ mode,
13370
+ pendingInitialStdin: typeof payload.stdin === "string" ? payload.stdin : "",
13371
+ pendingInitialArgvPrompt: trimmedArgvPrompt,
13234
13372
  earlyOutput: "",
13373
+ postSeedOutput: "",
13374
+ bannerObserved: false,
13235
13375
  readinessObserved: false,
13236
- initialPromptSeeded: false,
13376
+ initialPromptSeeded: mode !== "seed_after_prompt",
13237
13377
  readinessTimer: null,
13238
13378
  settled: false,
13239
13379
  waitForReady,
@@ -13243,9 +13383,10 @@ function createStartupState(payload) {
13243
13383
  if (startup.readinessTimer) clearTimeout(startup.readinessTimer);
13244
13384
  resolveReady();
13245
13385
  },
13246
- markFailed: (error) => {
13386
+ markFailed: (error, failureClass) => {
13247
13387
  if (startup.settled) return;
13248
13388
  startup.settled = true;
13389
+ startup.failureClass = failureClass;
13249
13390
  if (startup.readinessTimer) clearTimeout(startup.readinessTimer);
13250
13391
  rejectReady(new Error(error));
13251
13392
  }
@@ -13259,9 +13400,9 @@ function armStartupTimeout(session, proc) {
13259
13400
  }
13260
13401
  const timeoutMs = getCodexStartupReadyTimeoutMs();
13261
13402
  startup.readinessTimer = setTimeout(() => {
13262
- const error = `Codex PTY readiness timeout after ${timeoutMs}ms for ${session.agent_run_id}.`;
13403
+ const error = startup.mode === "seed_after_prompt" ? startup.initialPromptSeeded ? `STARTUP_TIMEOUT: Codex PTY startup acceptance was not observed within ${timeoutMs}ms for ${session.agent_run_id}.` : `STARTUP_TIMEOUT: Codex PTY prompt was not observed within ${timeoutMs}ms for ${session.agent_run_id}.` : startup.mode === "prompt_ready" ? `STARTUP_TIMEOUT: Codex PTY prompt was not observed within ${timeoutMs}ms for ${session.agent_run_id}.` : `STARTUP_TIMEOUT: Codex PTY startup output was not observed within ${timeoutMs}ms for ${session.agent_run_id}.`;
13263
13404
  console.error(`[PTY] EP1498: ${error}`);
13264
- startup.markFailed(error);
13405
+ startup.markFailed(error, "STARTUP_TIMEOUT");
13265
13406
  try {
13266
13407
  proc.kill();
13267
13408
  } catch (killError) {
@@ -13269,29 +13410,162 @@ function armStartupTimeout(session, proc) {
13269
13410
  }
13270
13411
  }, timeoutMs);
13271
13412
  }
13272
- function maybeSeedBufferedInitialPrompt(session, data) {
13413
+ function handleStartupData(session, data) {
13273
13414
  const startup = session.startup;
13274
- if (!startup || startup.initialPromptSeeded) {
13415
+ if (!startup) {
13275
13416
  return;
13276
13417
  }
13277
- if (!startup.readinessObserved) {
13278
- startup.earlyOutput += data;
13418
+ startup.earlyOutput += data;
13419
+ const normalizedEarlyOutput = normalizeCodexStartupOutput(startup.earlyOutput);
13420
+ const detectedFailure = detectCodexStartupFailure(normalizedEarlyOutput);
13421
+ if (detectedFailure) {
13422
+ const error = `${detectedFailure.failureClass}: ${detectedFailure.message}`;
13423
+ console.error(`[PTY] EP1514: ${error}`);
13424
+ startup.markFailed(error, detectedFailure.failureClass);
13425
+ try {
13426
+ session.pty.kill();
13427
+ } catch (killError) {
13428
+ console.warn(`[PTY] EP1514: Failed to kill failed startup PTY for ${session.agent_run_id}:`, killError);
13429
+ }
13430
+ return;
13279
13431
  }
13280
- const normalizedEarlyOutput = startup.earlyOutput.replace(ANSI_ESCAPE_CODE_REGEX, "");
13281
- if (!startup.readinessObserved && CODEX_READINESS_SIGNAL.test(normalizedEarlyOutput)) {
13282
- startup.readinessObserved = true;
13283
- startup.earlyOutput = "";
13432
+ if (!startup.bannerObserved && CODEX_BANNER_SIGNAL.test(normalizedEarlyOutput)) {
13433
+ startup.bannerObserved = true;
13284
13434
  }
13285
- if (!startup.readinessObserved) {
13435
+ if (startup.mode === "seed_after_prompt" && !startup.initialPromptSeeded) {
13436
+ if (!startup.bannerObserved || !CODEX_PROMPT_SIGNAL.test(normalizedEarlyOutput)) {
13437
+ return;
13438
+ }
13439
+ session.pty.write(`${startup.pendingInitialStdin}\r`);
13440
+ startup.initialPromptSeeded = true;
13441
+ startup.postSeedOutput = "";
13286
13442
  return;
13287
13443
  }
13288
- session.pty.write(`${startup.pendingInitialStdin}\r`);
13289
- startup.initialPromptSeeded = true;
13444
+ if (startup.mode === "prompt_ready") {
13445
+ if (!startup.bannerObserved || !CODEX_PROMPT_SIGNAL.test(normalizedEarlyOutput)) {
13446
+ return;
13447
+ }
13448
+ } else {
13449
+ startup.postSeedOutput += data;
13450
+ const normalizedPostSeedOutput = normalizeCodexStartupOutput(
13451
+ startup.mode === "seed_after_prompt" ? startup.postSeedOutput : startup.earlyOutput
13452
+ );
13453
+ const readinessOutput = startup.mode === "first_output" ? stripEchoedCodexStartupInput(normalizedPostSeedOutput, startup.pendingInitialArgvPrompt) : normalizedPostSeedOutput;
13454
+ if (!hasMeaningfulCodexStartupAcceptance(readinessOutput, [startup.pendingInitialStdin])) {
13455
+ return;
13456
+ }
13457
+ }
13458
+ if (startup.readinessObserved) {
13459
+ return;
13460
+ }
13461
+ startup.readinessObserved = true;
13462
+ startup.startupConfirmedAt = (/* @__PURE__ */ new Date()).toISOString();
13290
13463
  startup.markReady();
13291
13464
  }
13292
13465
  function getCodexStartupReadyTimeoutMs() {
13293
- const parsed = Number(process.env.EPISODA_CODEX_READY_TIMEOUT_MS || "8000");
13294
- return Number.isFinite(parsed) && parsed > 0 ? parsed : 8e3;
13466
+ const parsed = Number(process.env.EPISODA_CODEX_READY_TIMEOUT_MS || String(MAX_CODEX_STARTUP_READY_TIMEOUT_MS));
13467
+ if (!Number.isFinite(parsed) || parsed <= 0) {
13468
+ return MAX_CODEX_STARTUP_READY_TIMEOUT_MS;
13469
+ }
13470
+ return Math.min(parsed, MAX_CODEX_STARTUP_READY_TIMEOUT_MS);
13471
+ }
13472
+ function detectCodexStartupFailure(normalizedOutput) {
13473
+ const loweredOutput = normalizedOutput.toLowerCase();
13474
+ if (loweredOutput.includes("do you trust the contents of this directory?")) {
13475
+ return {
13476
+ failureClass: "TRUST_PROMPT_STALL",
13477
+ message: "Codex prompted for directory trust during non-interactive startup."
13478
+ };
13479
+ }
13480
+ if (loweredOutput.includes("access token could not be refreshed")) {
13481
+ return {
13482
+ failureClass: "OAUTH_REFRESH_ROTATION_CONFLICT",
13483
+ message: "Codex attempted refresh-token rotation against externally managed auth."
13484
+ };
13485
+ }
13486
+ if (loweredOutput.includes("--effort") && (loweredOutput.includes("unknown option") || loweredOutput.includes("unexpected argument") || loweredOutput.includes("unrecognized option") || loweredOutput.includes("unexpected value"))) {
13487
+ return {
13488
+ failureClass: "UNSUPPORTED_FLAG",
13489
+ message: "Codex rejected the unsupported --effort launch flag."
13490
+ };
13491
+ }
13492
+ if (/\b(?:unknown|invalid|unsupported)\b[^\n]*\bmodel\b/i.test(normalizedOutput) || /\bmodel\b[^\n]*(?:not supported|unsupported|unknown|invalid)\b/i.test(normalizedOutput) || /\b(?:400|bad request)\b[^\n]*\bmodel\b/i.test(normalizedOutput)) {
13493
+ return {
13494
+ failureClass: "MODEL_UNSUPPORTED",
13495
+ message: "Codex rejected an unsupported model during startup."
13496
+ };
13497
+ }
13498
+ return null;
13499
+ }
13500
+ function normalizeCodexStartupOutput(output) {
13501
+ return output.replace(ANSI_ESCAPE_CODE_REGEX, "").replace(/\r/g, "");
13502
+ }
13503
+ function hasMeaningfulCodexStartupAcceptance(output, echoedInputs) {
13504
+ const withoutEchoes = echoedInputs.reduce((currentOutput, echoedInput) => {
13505
+ return stripEchoedCodexStartupInput(currentOutput, echoedInput);
13506
+ }, output);
13507
+ const sanitized = withoutEchoes.replace(/(?:^|\n)\s*openai codex\s*(?=\n|$)/gi, "\n").replace(/(?:^|\n)\s*model:[^\n]*/gi, "\n").replace(CODEX_PROMPT_SIGNAL, "").replace(/\s+/g, "");
13508
+ return sanitized.length > 0;
13509
+ }
13510
+ function stripEchoedCodexStartupInput(output, echoedInput) {
13511
+ const normalizedEcho = echoedInput.trim();
13512
+ if (normalizedEcho.length === 0) {
13513
+ return output;
13514
+ }
13515
+ let strippedOutput = output.replace(new RegExp(escapeRegExp(normalizedEcho), "g"), "");
13516
+ const whitespaceFlexiblePattern = buildWhitespaceFlexiblePattern(normalizedEcho);
13517
+ if (whitespaceFlexiblePattern) {
13518
+ strippedOutput = strippedOutput.replace(whitespaceFlexiblePattern, "");
13519
+ }
13520
+ return strippedOutput;
13521
+ }
13522
+ function buildWhitespaceFlexiblePattern(value) {
13523
+ const normalizedValue = value.trim().replace(/\s+/g, " ");
13524
+ if (normalizedValue.length === 0) {
13525
+ return null;
13526
+ }
13527
+ return new RegExp(normalizedValue.split(" ").map(escapeRegExp).join("\\s+"), "g");
13528
+ }
13529
+ function resolveCodexArgvPrompt(args) {
13530
+ const positionalArgs = [];
13531
+ for (let index = 0; index < args.length; index += 1) {
13532
+ const current = args[index];
13533
+ if (!current) {
13534
+ continue;
13535
+ }
13536
+ if (current === "--model" || current === "--sandbox" || current === "-c") {
13537
+ index += 1;
13538
+ continue;
13539
+ }
13540
+ if (current.startsWith("--model=") || current.startsWith("--sandbox=") || current.startsWith("-c=") || current.startsWith("--")) {
13541
+ continue;
13542
+ }
13543
+ positionalArgs.push(current);
13544
+ }
13545
+ return positionalArgs.length === 0 ? "" : positionalArgs[positionalArgs.length - 1].trim();
13546
+ }
13547
+ function escapeRegExp(value) {
13548
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13549
+ }
13550
+ function buildPtyLaunchConfig(params) {
13551
+ const { command, args, env, cwd, bootstrap } = params;
13552
+ const launchConfig = {
13553
+ command,
13554
+ args,
13555
+ env,
13556
+ cwd
13557
+ };
13558
+ if (bootstrap?.authPath) {
13559
+ launchConfig.auth_path = bootstrap.authPath;
13560
+ }
13561
+ if (bootstrap?.configPath) {
13562
+ launchConfig.config_path = bootstrap.configPath;
13563
+ }
13564
+ if (bootstrap?.codexHome) {
13565
+ launchConfig.codex_home = bootstrap.codexHome;
13566
+ launchConfig.trusted_project_root = bootstrap.trustedProjectRoot || null;
13567
+ }
13568
+ return launchConfig;
13295
13569
  }
13296
13570
  function cleanupCredentialDirs(dirs) {
13297
13571
  for (const dirPath of dirs) {
@@ -13304,6 +13578,17 @@ function cleanupCredentialDirs(dirs) {
13304
13578
  }
13305
13579
  }
13306
13580
  }
13581
+ function resolveCodexTrustedProjectRoot(payload) {
13582
+ const cwd = typeof payload.cwd === "string" ? payload.cwd.trim() : "";
13583
+ const envWorktreeDir = typeof payload.env?.EPISODA_WORKTREE_DIR === "string" ? payload.env.EPISODA_WORKTREE_DIR.trim() : "";
13584
+ if (cwd.length > 0) {
13585
+ return cwd;
13586
+ }
13587
+ if (envWorktreeDir.length > 0) {
13588
+ return envWorktreeDir;
13589
+ }
13590
+ return process.cwd();
13591
+ }
13307
13592
 
13308
13593
  // src/utils/dev-server.ts
13309
13594
  var import_child_process16 = require("child_process");
@@ -15095,7 +15380,12 @@ var ProjectMessageRouter = class {
15095
15380
  moduleUid: resolvedPayload.moduleUid,
15096
15381
  agent_run_id: resolvedPayload.agent_run_id,
15097
15382
  success: result.success,
15098
- error: result.error
15383
+ error: result.error,
15384
+ startupFailureClass: result.startupFailureClass,
15385
+ startupConfirmedAt: result.startupConfirmedAt,
15386
+ modelUsed: result.modelUsed,
15387
+ launchConfig: result.launchConfig,
15388
+ authPath: result.authPath
15099
15389
  });
15100
15390
  }
15101
15391
  });