@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.
|
|
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
|
-
|
|
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
|
-
...
|
|
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
|
-
|
|
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 {
|
|
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
|
-
},
|
|
13213
|
-
|
|
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(
|
|
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.
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
|
13413
|
+
function handleStartupData(session, data) {
|
|
13273
13414
|
const startup = session.startup;
|
|
13274
|
-
if (!startup
|
|
13415
|
+
if (!startup) {
|
|
13275
13416
|
return;
|
|
13276
13417
|
}
|
|
13277
|
-
|
|
13278
|
-
|
|
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
|
-
|
|
13281
|
-
|
|
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.
|
|
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
|
-
|
|
13289
|
-
|
|
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 ||
|
|
13294
|
-
|
|
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
|
});
|