@episoda/cli 0.2.208 → 0.2.209

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.208",
3054
+ version: "0.2.209",
3055
3055
  description: "CLI tool for Episoda local development workflow orchestration",
3056
3056
  main: "dist/index.js",
3057
3057
  types: "dist/index.d.ts",
@@ -12989,6 +12989,7 @@ var fs31 = __toESM(require("fs"));
12989
12989
  var os14 = __toESM(require("os"));
12990
12990
  var path31 = __toESM(require("path"));
12991
12991
  var INACTIVITY_TIMEOUT_MS3 = 30 * 60 * 1e3;
12992
+ var CODEX_READINESS_SIGNAL = /OpenAI Codex/i;
12992
12993
  var sessions = /* @__PURE__ */ new Map();
12993
12994
  async function handlePtySpawn(payload, client) {
12994
12995
  const {
@@ -13049,7 +13050,8 @@ async function handlePtySpawn(payload, client) {
13049
13050
  lastOutputAt: Date.now(),
13050
13051
  watchdogTimer: null,
13051
13052
  credentialDirs: bootstrap.cleanupDirs,
13052
- credentialAuthPath: bootstrap.authPath
13053
+ credentialAuthPath: bootstrap.authPath,
13054
+ startup: createStartupState(payload)
13053
13055
  };
13054
13056
  sessions.set(agent_run_id, session);
13055
13057
  const resetWatchdog = () => {
@@ -13066,6 +13068,7 @@ async function handlePtySpawn(payload, client) {
13066
13068
  resetWatchdog();
13067
13069
  proc.onData((data) => {
13068
13070
  resetWatchdog();
13071
+ maybeSeedBufferedInitialPrompt(session, data);
13069
13072
  client.send({
13070
13073
  type: "pty_data",
13071
13074
  moduleUid,
@@ -13075,10 +13078,15 @@ async function handlePtySpawn(payload, client) {
13075
13078
  console.error(`[PTY] Failed to send pty_data for ${agent_run_id}:`, err.message);
13076
13079
  });
13077
13080
  });
13078
- if (typeof stdin === "string" && stdin.trim().length > 0) {
13081
+ if (typeof stdin === "string" && stdin.trim().length > 0 && !session.startup) {
13079
13082
  proc.write(`${stdin}\r`);
13080
13083
  }
13081
13084
  proc.onExit(({ exitCode }) => {
13085
+ if (session.startup && !session.startup.readinessObserved) {
13086
+ session.startup.markFailed(
13087
+ `Codex PTY exited before startup readiness for ${agent_run_id} (exit code ${exitCode}).`
13088
+ );
13089
+ }
13082
13090
  const durationMs = Date.now() - session.startedAt;
13083
13091
  if (session.watchdogTimer) clearTimeout(session.watchdogTimer);
13084
13092
  console.log(`[PTY] Process exited for ${agent_run_id} with code ${exitCode} after ${durationMs}ms`);
@@ -13094,6 +13102,17 @@ async function handlePtySpawn(payload, client) {
13094
13102
  });
13095
13103
  syncCredentialUpdateAfterExit(session, agent_run_id, client);
13096
13104
  });
13105
+ if (session.startup) {
13106
+ armStartupTimeout(session, proc);
13107
+ try {
13108
+ await session.startup.waitForReady;
13109
+ } catch (error) {
13110
+ return {
13111
+ success: false,
13112
+ error: error?.message || "Codex PTY failed before startup readiness"
13113
+ };
13114
+ }
13115
+ }
13097
13116
  return { success: true };
13098
13117
  }
13099
13118
  function handlePtyResize(payload) {
@@ -13198,6 +13217,79 @@ function createCredentialBootstrap(payload, agentRunId) {
13198
13217
  authPath
13199
13218
  };
13200
13219
  }
13220
+ function createStartupState(payload) {
13221
+ if (payload.run_type !== "persistent" || payload.command !== "codex" || typeof payload.stdin !== "string" || payload.stdin.trim().length === 0) {
13222
+ return void 0;
13223
+ }
13224
+ let resolveReady;
13225
+ let rejectReady;
13226
+ const waitForReady = new Promise((resolve9, reject) => {
13227
+ resolveReady = resolve9;
13228
+ rejectReady = reject;
13229
+ });
13230
+ const startup = {
13231
+ pendingInitialStdin: payload.stdin,
13232
+ earlyOutput: "",
13233
+ readinessObserved: false,
13234
+ initialPromptSeeded: false,
13235
+ readinessTimer: null,
13236
+ settled: false,
13237
+ waitForReady,
13238
+ markReady: () => {
13239
+ if (startup.settled) return;
13240
+ startup.settled = true;
13241
+ if (startup.readinessTimer) clearTimeout(startup.readinessTimer);
13242
+ resolveReady();
13243
+ },
13244
+ markFailed: (error) => {
13245
+ if (startup.settled) return;
13246
+ startup.settled = true;
13247
+ if (startup.readinessTimer) clearTimeout(startup.readinessTimer);
13248
+ rejectReady(new Error(error));
13249
+ }
13250
+ };
13251
+ return startup;
13252
+ }
13253
+ function armStartupTimeout(session, proc) {
13254
+ const startup = session.startup;
13255
+ if (!startup || startup.readinessTimer) {
13256
+ return;
13257
+ }
13258
+ const timeoutMs = getCodexStartupReadyTimeoutMs();
13259
+ startup.readinessTimer = setTimeout(() => {
13260
+ const error = `Codex PTY readiness timeout after ${timeoutMs}ms for ${session.agent_run_id}.`;
13261
+ console.error(`[PTY] EP1498: ${error}`);
13262
+ startup.markFailed(error);
13263
+ try {
13264
+ proc.kill();
13265
+ } catch (killError) {
13266
+ console.warn(`[PTY] EP1498: Failed to kill timed-out startup PTY for ${session.agent_run_id}:`, killError);
13267
+ }
13268
+ }, timeoutMs);
13269
+ }
13270
+ function maybeSeedBufferedInitialPrompt(session, data) {
13271
+ const startup = session.startup;
13272
+ if (!startup || startup.initialPromptSeeded) {
13273
+ return;
13274
+ }
13275
+ if (!startup.readinessObserved) {
13276
+ startup.earlyOutput += data;
13277
+ }
13278
+ if (!startup.readinessObserved && CODEX_READINESS_SIGNAL.test(startup.earlyOutput)) {
13279
+ startup.readinessObserved = true;
13280
+ startup.earlyOutput = "";
13281
+ }
13282
+ if (!startup.readinessObserved) {
13283
+ return;
13284
+ }
13285
+ session.pty.write(`${startup.pendingInitialStdin}\r`);
13286
+ startup.initialPromptSeeded = true;
13287
+ startup.markReady();
13288
+ }
13289
+ function getCodexStartupReadyTimeoutMs() {
13290
+ const parsed = Number(process.env.EPISODA_CODEX_READY_TIMEOUT_MS || "8000");
13291
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 8e3;
13292
+ }
13201
13293
  function syncCredentialUpdateAfterExit(session, agent_run_id, client) {
13202
13294
  const authPath = session.credentialAuthPath;
13203
13295
  if (!authPath) {