@episoda/cli 0.2.215 → 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,7 +3051,7 @@ var require_package = __commonJS({
|
|
|
3051
3051
|
"package.json"(exports2, module2) {
|
|
3052
3052
|
module2.exports = {
|
|
3053
3053
|
name: "@episoda/cli",
|
|
3054
|
-
version: "0.2.
|
|
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",
|
|
@@ -4804,6 +4804,93 @@ async function ensureCodexBinary() {
|
|
|
4804
4804
|
|
|
4805
4805
|
// src/agent/providers/codex-config.ts
|
|
4806
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
|
+
}
|
|
4807
4894
|
function generateCodexAuthJson(credentials) {
|
|
4808
4895
|
const tokens = {
|
|
4809
4896
|
id_token: credentials.idToken || credentials.accessToken,
|
|
@@ -12991,8 +13078,10 @@ var fs31 = __toESM(require("fs"));
|
|
|
12991
13078
|
var os14 = __toESM(require("os"));
|
|
12992
13079
|
var path31 = __toESM(require("path"));
|
|
12993
13080
|
var INACTIVITY_TIMEOUT_MS3 = 30 * 60 * 1e3;
|
|
12994
|
-
var CODEX_READINESS_SIGNAL = /(?:\d+% left ·|\bmodel:\s+gpt-)/i;
|
|
12995
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;
|
|
12996
13085
|
var sessions = /* @__PURE__ */ new Map();
|
|
12997
13086
|
function killPtySessionsForModule(moduleUid) {
|
|
12998
13087
|
const killedRunIds = [];
|
|
@@ -13031,16 +13120,30 @@ async function handlePtySpawn(payload, client) {
|
|
|
13031
13120
|
console.log(`[PTY] Spawning PTY for ${moduleUid} / ${agent_run_id}: ${command} ${args.join(" ")}`);
|
|
13032
13121
|
let bootstrap = null;
|
|
13033
13122
|
let proc;
|
|
13123
|
+
let modelUsed;
|
|
13124
|
+
let launchConfig;
|
|
13125
|
+
let spawnArgs = args;
|
|
13034
13126
|
try {
|
|
13035
13127
|
bootstrap = createCredentialBootstrap(payload, agent_run_id);
|
|
13036
|
-
|
|
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, {
|
|
13037
13140
|
name: "xterm-256color",
|
|
13038
13141
|
cols,
|
|
13039
13142
|
rows,
|
|
13040
13143
|
cwd: cwd || process.cwd(),
|
|
13041
13144
|
env: {
|
|
13042
13145
|
...process.env,
|
|
13043
|
-
...
|
|
13146
|
+
...spawnEnv,
|
|
13044
13147
|
...bootstrap.env
|
|
13045
13148
|
}
|
|
13046
13149
|
});
|
|
@@ -13058,7 +13161,10 @@ async function handlePtySpawn(payload, client) {
|
|
|
13058
13161
|
});
|
|
13059
13162
|
return {
|
|
13060
13163
|
success: false,
|
|
13061
|
-
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
|
|
13062
13168
|
};
|
|
13063
13169
|
}
|
|
13064
13170
|
const session = {
|
|
@@ -13070,7 +13176,7 @@ async function handlePtySpawn(payload, client) {
|
|
|
13070
13176
|
lastOutputAt: Date.now(),
|
|
13071
13177
|
watchdogTimer: null,
|
|
13072
13178
|
credentialDirs: bootstrap.cleanupDirs,
|
|
13073
|
-
startup: createStartupState(payload)
|
|
13179
|
+
startup: createStartupState(payload, spawnArgs)
|
|
13074
13180
|
};
|
|
13075
13181
|
sessions.set(agent_run_id, session);
|
|
13076
13182
|
const resetWatchdog = () => {
|
|
@@ -13087,7 +13193,7 @@ async function handlePtySpawn(payload, client) {
|
|
|
13087
13193
|
resetWatchdog();
|
|
13088
13194
|
proc.onData((data) => {
|
|
13089
13195
|
resetWatchdog();
|
|
13090
|
-
|
|
13196
|
+
handleStartupData(session, data);
|
|
13091
13197
|
client.send({
|
|
13092
13198
|
type: "pty_data",
|
|
13093
13199
|
moduleUid,
|
|
@@ -13103,7 +13209,8 @@ async function handlePtySpawn(payload, client) {
|
|
|
13103
13209
|
proc.onExit(({ exitCode }) => {
|
|
13104
13210
|
if (session.startup && !session.startup.readinessObserved) {
|
|
13105
13211
|
session.startup.markFailed(
|
|
13106
|
-
`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"
|
|
13107
13214
|
);
|
|
13108
13215
|
}
|
|
13109
13216
|
const durationMs = Date.now() - session.startedAt;
|
|
@@ -13128,11 +13235,22 @@ async function handlePtySpawn(payload, client) {
|
|
|
13128
13235
|
} catch (error) {
|
|
13129
13236
|
return {
|
|
13130
13237
|
success: false,
|
|
13131
|
-
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
|
|
13132
13244
|
};
|
|
13133
13245
|
}
|
|
13134
13246
|
}
|
|
13135
|
-
return {
|
|
13247
|
+
return {
|
|
13248
|
+
success: true,
|
|
13249
|
+
startupConfirmedAt: session.startup?.startupConfirmedAt,
|
|
13250
|
+
modelUsed,
|
|
13251
|
+
launchConfig,
|
|
13252
|
+
authPath: bootstrap.authPath
|
|
13253
|
+
};
|
|
13136
13254
|
}
|
|
13137
13255
|
function handlePtyResize(payload) {
|
|
13138
13256
|
const { agent_run_id, cols, rows } = payload;
|
|
@@ -13207,29 +13325,40 @@ function createCredentialBootstrap(payload, agentRunId) {
|
|
|
13207
13325
|
fs31.writeFileSync(credentialsPath, JSON.stringify({ claudeAiOauth }, null, 2), { mode: 384 });
|
|
13208
13326
|
return {
|
|
13209
13327
|
env: { CLAUDE_CONFIG_DIR: claudeConfigDir },
|
|
13210
|
-
cleanupDirs
|
|
13328
|
+
cleanupDirs,
|
|
13329
|
+
authPath: credentialsPath
|
|
13211
13330
|
};
|
|
13212
13331
|
}
|
|
13213
13332
|
const codexHome = path31.join(baseDir, ".codex");
|
|
13214
13333
|
fs31.mkdirSync(codexHome, { recursive: true });
|
|
13334
|
+
const trustedProjectRoot = resolveCodexTrustedProjectRoot(payload);
|
|
13215
13335
|
const configFiles = generateCodexConfig({
|
|
13216
13336
|
accessToken: bootstrap.oauth.access_token,
|
|
13217
13337
|
idToken: bootstrap.oauth.id_token,
|
|
13218
13338
|
accountId: bootstrap.oauth.account_id
|
|
13219
|
-
},
|
|
13220
|
-
|
|
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 });
|
|
13221
13343
|
if (configFiles["config.toml"]) {
|
|
13222
|
-
fs31.writeFileSync(
|
|
13344
|
+
fs31.writeFileSync(configPath, configFiles["config.toml"], { mode: 384 });
|
|
13223
13345
|
}
|
|
13224
13346
|
return {
|
|
13225
13347
|
env: { CODEX_HOME: codexHome },
|
|
13226
|
-
cleanupDirs
|
|
13348
|
+
cleanupDirs,
|
|
13349
|
+
authPath,
|
|
13350
|
+
configPath,
|
|
13351
|
+
codexHome,
|
|
13352
|
+
trustedProjectRoot
|
|
13227
13353
|
};
|
|
13228
13354
|
}
|
|
13229
|
-
function createStartupState(payload) {
|
|
13230
|
-
if (payload.
|
|
13355
|
+
function createStartupState(payload, resolvedArgs) {
|
|
13356
|
+
if (payload.command !== "codex") {
|
|
13231
13357
|
return void 0;
|
|
13232
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";
|
|
13233
13362
|
let resolveReady;
|
|
13234
13363
|
let rejectReady;
|
|
13235
13364
|
const waitForReady = new Promise((resolve9, reject) => {
|
|
@@ -13237,10 +13366,14 @@ function createStartupState(payload) {
|
|
|
13237
13366
|
rejectReady = reject;
|
|
13238
13367
|
});
|
|
13239
13368
|
const startup = {
|
|
13240
|
-
|
|
13369
|
+
mode,
|
|
13370
|
+
pendingInitialStdin: typeof payload.stdin === "string" ? payload.stdin : "",
|
|
13371
|
+
pendingInitialArgvPrompt: trimmedArgvPrompt,
|
|
13241
13372
|
earlyOutput: "",
|
|
13373
|
+
postSeedOutput: "",
|
|
13374
|
+
bannerObserved: false,
|
|
13242
13375
|
readinessObserved: false,
|
|
13243
|
-
initialPromptSeeded:
|
|
13376
|
+
initialPromptSeeded: mode !== "seed_after_prompt",
|
|
13244
13377
|
readinessTimer: null,
|
|
13245
13378
|
settled: false,
|
|
13246
13379
|
waitForReady,
|
|
@@ -13250,9 +13383,10 @@ function createStartupState(payload) {
|
|
|
13250
13383
|
if (startup.readinessTimer) clearTimeout(startup.readinessTimer);
|
|
13251
13384
|
resolveReady();
|
|
13252
13385
|
},
|
|
13253
|
-
markFailed: (error) => {
|
|
13386
|
+
markFailed: (error, failureClass) => {
|
|
13254
13387
|
if (startup.settled) return;
|
|
13255
13388
|
startup.settled = true;
|
|
13389
|
+
startup.failureClass = failureClass;
|
|
13256
13390
|
if (startup.readinessTimer) clearTimeout(startup.readinessTimer);
|
|
13257
13391
|
rejectReady(new Error(error));
|
|
13258
13392
|
}
|
|
@@ -13266,9 +13400,9 @@ function armStartupTimeout(session, proc) {
|
|
|
13266
13400
|
}
|
|
13267
13401
|
const timeoutMs = getCodexStartupReadyTimeoutMs();
|
|
13268
13402
|
startup.readinessTimer = setTimeout(() => {
|
|
13269
|
-
const error = `Codex PTY
|
|
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}.`;
|
|
13270
13404
|
console.error(`[PTY] EP1498: ${error}`);
|
|
13271
|
-
startup.markFailed(error);
|
|
13405
|
+
startup.markFailed(error, "STARTUP_TIMEOUT");
|
|
13272
13406
|
try {
|
|
13273
13407
|
proc.kill();
|
|
13274
13408
|
} catch (killError) {
|
|
@@ -13276,29 +13410,162 @@ function armStartupTimeout(session, proc) {
|
|
|
13276
13410
|
}
|
|
13277
13411
|
}, timeoutMs);
|
|
13278
13412
|
}
|
|
13279
|
-
function
|
|
13413
|
+
function handleStartupData(session, data) {
|
|
13280
13414
|
const startup = session.startup;
|
|
13281
|
-
if (!startup
|
|
13415
|
+
if (!startup) {
|
|
13282
13416
|
return;
|
|
13283
13417
|
}
|
|
13284
|
-
|
|
13285
|
-
|
|
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;
|
|
13286
13431
|
}
|
|
13287
|
-
|
|
13288
|
-
|
|
13289
|
-
startup.readinessObserved = true;
|
|
13290
|
-
startup.earlyOutput = "";
|
|
13432
|
+
if (!startup.bannerObserved && CODEX_BANNER_SIGNAL.test(normalizedEarlyOutput)) {
|
|
13433
|
+
startup.bannerObserved = true;
|
|
13291
13434
|
}
|
|
13292
|
-
if (!startup.
|
|
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 = "";
|
|
13293
13442
|
return;
|
|
13294
13443
|
}
|
|
13295
|
-
|
|
13296
|
-
|
|
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();
|
|
13297
13463
|
startup.markReady();
|
|
13298
13464
|
}
|
|
13299
13465
|
function getCodexStartupReadyTimeoutMs() {
|
|
13300
|
-
const parsed = Number(process.env.EPISODA_CODEX_READY_TIMEOUT_MS ||
|
|
13301
|
-
|
|
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;
|
|
13302
13569
|
}
|
|
13303
13570
|
function cleanupCredentialDirs(dirs) {
|
|
13304
13571
|
for (const dirPath of dirs) {
|
|
@@ -13311,6 +13578,17 @@ function cleanupCredentialDirs(dirs) {
|
|
|
13311
13578
|
}
|
|
13312
13579
|
}
|
|
13313
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
|
+
}
|
|
13314
13592
|
|
|
13315
13593
|
// src/utils/dev-server.ts
|
|
13316
13594
|
var import_child_process16 = require("child_process");
|
|
@@ -15102,7 +15380,12 @@ var ProjectMessageRouter = class {
|
|
|
15102
15380
|
moduleUid: resolvedPayload.moduleUid,
|
|
15103
15381
|
agent_run_id: resolvedPayload.agent_run_id,
|
|
15104
15382
|
success: result.success,
|
|
15105
|
-
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
|
|
15106
15389
|
});
|
|
15107
15390
|
}
|
|
15108
15391
|
});
|