replicas-engine 0.1.636 → 0.1.637

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.
@@ -89,8 +89,8 @@ var REPLICAS_RUNTIME_ENV_ALIASES = {
89
89
  slackChannelId: ["REPLICAS_SLACK_CHANNEL_ID", "SLACK_CHANNEL_ID"],
90
90
  slackThreadTs: ["REPLICAS_SLACK_THREAD_TS", "SLACK_THREAD_TS"]
91
91
  };
92
- function readReplicasRuntimeEnv(readEnv2, [namespacedKey, legacyKey]) {
93
- return readEnv2(namespacedKey) ?? readEnv2(legacyKey);
92
+ function readReplicasRuntimeEnv(readEnv, [namespacedKey, legacyKey]) {
93
+ return readEnv(namespacedKey) ?? readEnv(legacyKey);
94
94
  }
95
95
  function shellQuotePosix(value) {
96
96
  return `'${value.split("'").join("'\\''")}'`;
@@ -5643,150 +5643,19 @@ async function putPresignedFile(urlValue, filePath, size, contentType) {
5643
5643
  });
5644
5644
  }
5645
5645
 
5646
- // src/engine-env.ts
5647
- import { readFileSync as readFileSync2 } from "fs";
5648
- import { homedir as homedir2 } from "os";
5649
- import { join as join2 } from "path";
5650
-
5651
- // src/runtime-env-loader.ts
5652
- import { readFileSync } from "fs";
5653
- import { homedir } from "os";
5654
- import { join } from "path";
5655
- function loadRuntimeEnvFile() {
5656
- let content;
5657
- try {
5658
- content = readFileSync(join(homedir(), ".replicas", "runtime-env.sh"), "utf-8");
5659
- } catch {
5660
- return;
5661
- }
5662
- for (const [key, value] of Object.entries(parsePosixEnvFile(content))) {
5663
- process.env[key] = value;
5664
- }
5665
- }
5666
-
5667
- // src/utils/type-guards.ts
5668
- function isRecord4(value) {
5669
- return typeof value === "object" && value !== null;
5670
- }
5671
-
5672
- // src/engine-env.ts
5673
- var SANDBOX_IMAGE_VERSION_FILE = "/usr/local/lib/replicas-sandbox-image-version";
5674
- function readEnv(name) {
5675
- const value = process.env[name]?.trim();
5676
- return value ? value : void 0;
5677
- }
5678
- function readSandboxImageVersion() {
5679
- const environmentVersion = readEnv("REPLICAS_SANDBOX_IMAGE_VERSION");
5680
- if (environmentVersion) return environmentVersion;
5681
- try {
5682
- return readFileSync2(SANDBOX_IMAGE_VERSION_FILE, "utf8").trim() || "development";
5683
- } catch {
5684
- return "development";
5685
- }
5686
- }
5687
- function parsePort(value) {
5688
- if (!value) {
5689
- return 3737;
5690
- }
5691
- const parsed = Number(value);
5692
- if (!Number.isInteger(parsed) || parsed <= 0) {
5693
- throw new Error("Invalid engine environment: REPLICAS_ENGINE_PORT must be a positive integer");
5694
- }
5695
- return parsed;
5696
- }
5697
- function requireDefined(value, name) {
5698
- if (value === void 0 || value === null) {
5699
- throw new Error(`Invalid engine environment: ${name} is required`);
5700
- }
5701
- return value;
5702
- }
5703
- function requireValidURL(value, name) {
5704
- try {
5705
- new URL(value);
5706
- return value;
5707
- } catch {
5708
- throw new Error(`Invalid engine environment: ${name} must be a valid URL`);
5709
- }
5710
- }
5711
- function parseClaudeAuthMethod(value) {
5712
- if (value === "oauth" || value === "api_key" || value === "bedrock" || value === "foundry") {
5713
- return value;
5714
- }
5715
- return void 0;
5716
- }
5717
- function parseCodexAuthMethod(value) {
5718
- if (value === "oauth" || value === "api_key" || value === "foundry") {
5719
- return value;
5720
- }
5721
- return void 0;
5722
- }
5723
- function parseAgentCredentialSnapshots(value) {
5724
- if (!value) return {};
5725
- try {
5726
- const parsed = JSON.parse(value);
5727
- if (!isRecord4(parsed)) return {};
5728
- const snapshots = {};
5729
- for (const [provider, snapshot] of Object.entries(parsed)) {
5730
- if (!isValidAgentProvider(provider)) continue;
5731
- const parsedSnapshot = agentCredentialSnapshotSchema.safeParse(snapshot);
5732
- if (parsedSnapshot.success) snapshots[provider] = parsedSnapshot.data;
5733
- }
5734
- return snapshots;
5735
- } catch {
5736
- return {};
5737
- }
5738
- }
5739
- var IS_WARMING_MODE = process.argv.includes("--warming");
5740
- function loadEngineEnv() {
5741
- loadRuntimeEnvFile();
5742
- const HOME_DIR = homedir2();
5743
- const env = {
5744
- // Defined: always available
5745
- REPLICAS_ENGINE_SECRET: requireDefined(readEnv("REPLICAS_ENGINE_SECRET"), "REPLICAS_ENGINE_SECRET"),
5746
- REPLICAS_ENGINE_PORT: parsePort(readEnv("REPLICAS_ENGINE_PORT")),
5747
- REPLICAS_MONOLITH_URL: requireValidURL(
5748
- requireDefined(readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.monolithUrl), "REPLICAS_MONOLITH_URL"),
5749
- "REPLICAS_MONOLITH_URL"
5750
- ),
5751
- HOME_DIR,
5752
- WORKSPACE_ROOT: join2(HOME_DIR, "workspaces"),
5753
- REPLICAS_SANDBOX_IMAGE_VERSION: readSandboxImageVersion(),
5754
- // Runtime: may not be set during warming
5755
- REPLICAS_WORKSPACE_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.workspaceId),
5756
- REPLICAS_LINEAR_SESSION_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.linearSessionId),
5757
- REPLICAS_LINEAR_ACCESS_TOKEN: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.linearAccessToken),
5758
- REPLICAS_SLACK_BOT_TOKEN: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackBotToken),
5759
- REPLICAS_SLACK_CHANNEL_ID: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackChannelId),
5760
- REPLICAS_SLACK_THREAD_TS: readReplicasRuntimeEnv(readEnv, REPLICAS_RUNTIME_ENV_ALIASES.slackThreadTs),
5761
- ANTHROPIC_API_KEY: readEnv("ANTHROPIC_API_KEY"),
5762
- OPENAI_API_KEY: readEnv("OPENAI_API_KEY"),
5763
- CURSOR_API_KEY: readEnv("CURSOR_API_KEY"),
5764
- CLAUDE_CODE_USE_BEDROCK: readEnv("CLAUDE_CODE_USE_BEDROCK"),
5765
- AWS_ACCESS_KEY_ID: readEnv("AWS_ACCESS_KEY_ID"),
5766
- AWS_SECRET_ACCESS_KEY: readEnv("AWS_SECRET_ACCESS_KEY"),
5767
- AWS_REGION: readEnv("AWS_REGION"),
5768
- ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION: readEnv("ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION"),
5769
- REPLICAS_CLAUDE_AUTH_METHOD: parseClaudeAuthMethod(readEnv("REPLICAS_CLAUDE_AUTH_METHOD")),
5770
- REPLICAS_CODEX_AUTH_METHOD: parseCodexAuthMethod(readEnv("REPLICAS_CODEX_AUTH_METHOD")),
5771
- REPLICAS_AGENT_CREDENTIALS: parseAgentCredentialSnapshots(readEnv("REPLICAS_AGENT_CREDENTIALS")),
5772
- REPLICAS_ENV_SYSTEM_PROMPT: readEnv("REPLICAS_ENV_SYSTEM_PROMPT"),
5773
- REPLICAS_ENV_START_HOOK: readEnv("REPLICAS_ENV_START_HOOK"),
5774
- REPLICAS_DISABLE_AUTO_START_HOOKS: readEnv("REPLICAS_DISABLE_AUTO_START_HOOKS")?.toLowerCase() === "true",
5775
- REPLICAS_ENGINE_DEFER_INITIALIZATION: readEnv("REPLICAS_ENGINE_DEFER_INITIALIZATION")?.toLowerCase() === "true"
5776
- };
5777
- if (!IS_WARMING_MODE && !env.REPLICAS_WORKSPACE_ID) {
5778
- console.error("REPLICAS_WORKSPACE_ID is not set \u2014 this is required in normal (non-warming) mode");
5646
+ // src/utils/codex-agent-env.ts
5647
+ function buildCodexAgentEnv(source = process.env) {
5648
+ const env = Object.fromEntries(
5649
+ Object.entries(source).filter((entry) => typeof entry[1] === "string")
5650
+ );
5651
+ if (env.REPLICAS_CODEX_AUTH_METHOD === "oauth" || env.REPLICAS_CODEX_AUTH_METHOD === "foundry") {
5652
+ delete env.OPENAI_API_KEY;
5779
5653
  }
5654
+ delete env.GH_TOKEN;
5655
+ delete env.GITHUB_TOKEN;
5656
+ delete env.GH_CONFIG_DIR;
5780
5657
  return env;
5781
5658
  }
5782
- var ENGINE_ENV = loadEngineEnv();
5783
- function setAgentCredentialSnapshot(provider, snapshot) {
5784
- ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS = {
5785
- ...ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS,
5786
- [provider]: snapshot
5787
- };
5788
- process.env.REPLICAS_AGENT_CREDENTIALS = JSON.stringify(ENGINE_ENV.REPLICAS_AGENT_CREDENTIALS);
5789
- }
5790
5659
 
5791
5660
  // src/utils/exec.ts
5792
5661
  import { exec, execFile } from "child_process";
@@ -5988,61 +5857,6 @@ var AspClient = class {
5988
5857
  }
5989
5858
  };
5990
5859
 
5991
- // src/utils/codex-agent-env.ts
5992
- function buildCodexAgentEnv(source = process.env) {
5993
- const env = Object.fromEntries(
5994
- Object.entries(source).filter((entry) => typeof entry[1] === "string")
5995
- );
5996
- if (env.REPLICAS_CODEX_AUTH_METHOD === "oauth" || env.REPLICAS_CODEX_AUTH_METHOD === "foundry") {
5997
- delete env.OPENAI_API_KEY;
5998
- }
5999
- delete env.GH_TOKEN;
6000
- delete env.GITHUB_TOKEN;
6001
- delete env.GH_CONFIG_DIR;
6002
- return env;
6003
- }
6004
-
6005
- // src/utils/agent-env.ts
6006
- function resolveClaudeAuthMethodForMessage(env = ENGINE_ENV) {
6007
- const method = env.REPLICAS_CLAUDE_AUTH_METHOD;
6008
- if (method && method !== "none") {
6009
- return method;
6010
- }
6011
- if (env.CLAUDE_CODE_USE_BEDROCK === "1") return "bedrock";
6012
- if (env.ANTHROPIC_API_KEY) return "api_key";
6013
- return "unknown";
6014
- }
6015
- function buildClaudeAgentEnv(overrides) {
6016
- const env = { ...process.env };
6017
- if (overrides) {
6018
- Object.assign(env, overrides);
6019
- }
6020
- const isBedrock = isClaudeBedrockEnv(env);
6021
- if (shouldStripAnthropicApiKey(isBedrock)) {
6022
- env.ANTHROPIC_API_KEY = void 0;
6023
- }
6024
- if (isBedrock) {
6025
- env.CLAUDE_CODE_USE_BEDROCK = "1";
6026
- env.CLAUDE_CODE_USE_MANTLE = "1";
6027
- env.ANTHROPIC_DEFAULT_OPUS_MODEL = CLAUDE_OPUS_4_8_BEDROCK_MODEL;
6028
- env.ANTHROPIC_DEFAULT_SONNET_MODEL = CLAUDE_SONNET_5_BEDROCK_MODEL;
6029
- env.ANTHROPIC_DEFAULT_HAIKU_MODEL = CLAUDE_HAIKU_4_5_BEDROCK_MODEL;
6030
- }
6031
- env.GH_TOKEN = void 0;
6032
- env.GITHUB_TOKEN = void 0;
6033
- env.GH_CONFIG_DIR = void 0;
6034
- env.CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD = "1";
6035
- env.CLAUDE_CODE_DISABLE_AUTO_MEMORY = "1";
6036
- return env;
6037
- }
6038
- function shouldStripAnthropicApiKey(isBedrock) {
6039
- const method = ENGINE_ENV.REPLICAS_CLAUDE_AUTH_METHOD;
6040
- return method === "oauth" || method === "bedrock" || method === "foundry" || isBedrock;
6041
- }
6042
- function isClaudeBedrockEnv(env) {
6043
- return ENGINE_ENV.REPLICAS_CLAUDE_AUTH_METHOD === "bedrock" || env.REPLICAS_CLAUDE_AUTH_METHOD === "bedrock" || env.CLAUDE_CODE_USE_BEDROCK === "1";
6044
- }
6045
-
6046
5860
  // src/managers/codex-asp/app-server-process.ts
6047
5861
  var DEFAULT_CODEX_BINARY = "codex";
6048
5862
  var DEFAULT_CODEX_ARGS = [
@@ -6059,7 +5873,7 @@ var DEFAULT_CODEX_ARGS = [
6059
5873
  var MIN_CODEX_CLI_VERSION = "0.144.6";
6060
5874
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
6061
5875
  var codexCliVersionEnsured = null;
6062
- var ENGINE_PACKAGE_VERSION = "0.1.636";
5876
+ var ENGINE_PACKAGE_VERSION = "0.1.637";
6063
5877
  var INITIALIZE_METHOD = "initialize";
6064
5878
  var INITIALIZED_NOTIFICATION = "initialized";
6065
5879
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -6072,26 +5886,26 @@ var AppServerProcess = class {
6072
5886
  child = null;
6073
5887
  client = null;
6074
5888
  shuttingDown = false;
6075
- constructor(options = {}) {
5889
+ constructor(options) {
6076
5890
  this.binary = options.binary ?? DEFAULT_CODEX_BINARY;
6077
- const baseArgs = options.args ?? (ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD === "foundry" ? [
5891
+ const baseArgs = options.args ?? (options.env.REPLICAS_CODEX_AUTH_METHOD === "foundry" ? [
6078
5892
  ...DEFAULT_CODEX_ARGS,
6079
5893
  "-c",
6080
- `model=${JSON.stringify(process.env.CODEX_FOUNDRY_MODEL)}`,
5894
+ `model=${JSON.stringify(options.env.CODEX_FOUNDRY_MODEL)}`,
6081
5895
  "-c",
6082
5896
  'model_provider="azure"',
6083
5897
  "-c",
6084
5898
  'model_providers.azure.name="Azure OpenAI"',
6085
5899
  "-c",
6086
- `model_providers.azure.base_url=${JSON.stringify(process.env.CODEX_FOUNDRY_BASE_URL)}`,
5900
+ `model_providers.azure.base_url=${JSON.stringify(options.env.CODEX_FOUNDRY_BASE_URL)}`,
6087
5901
  "-c",
6088
5902
  'model_providers.azure.env_key="AZURE_OPENAI_API_KEY"',
6089
5903
  "-c",
6090
5904
  'model_providers.azure.wire_api="responses"'
6091
5905
  ] : DEFAULT_CODEX_ARGS);
6092
5906
  this.args = [...baseArgs, ...(options.configOverrides ?? []).flatMap((override) => ["-c", override])];
6093
- this.env = options.env ?? buildCodexAgentEnv();
6094
- this.cwd = options.cwd ?? ENGINE_ENV.WORKSPACE_ROOT;
5907
+ this.env = options.env;
5908
+ this.cwd = options.cwd;
6095
5909
  }
6096
5910
  on(event, listener) {
6097
5911
  this.emitter.on(event, listener);
@@ -6213,12 +6027,12 @@ var AppServerProcess = class {
6213
6027
  console.warn(`[AppServerProcess] upgraded codex CLI to ${MIN_CODEX_CLI_VERSION}`);
6214
6028
  }
6215
6029
  async loginWithConfiguredApiKey(client) {
6216
- if (ENGINE_ENV.REPLICAS_CODEX_AUTH_METHOD !== "api_key" || !ENGINE_ENV.OPENAI_API_KEY) {
6030
+ if (this.env.REPLICAS_CODEX_AUTH_METHOD !== "api_key" || !this.env.OPENAI_API_KEY) {
6217
6031
  return;
6218
6032
  }
6219
6033
  const params = {
6220
6034
  type: "apiKey",
6221
- apiKey: ENGINE_ENV.OPENAI_API_KEY
6035
+ apiKey: this.env.OPENAI_API_KEY
6222
6036
  };
6223
6037
  await client.request(ACCOUNT_LOGIN_START_METHOD, params);
6224
6038
  }
@@ -6237,6 +6051,43 @@ var AppServerProcess = class {
6237
6051
  }
6238
6052
  };
6239
6053
 
6054
+ // src/managers/codex-asp/notification-dispatch.ts
6055
+ var TURN_STARTED_METHOD = "turn/started";
6056
+ var TURN_COMPLETED_METHOD = "turn/completed";
6057
+ var TURN_PLAN_UPDATED_METHOD = "turn/plan/updated";
6058
+ var THREAD_GOAL_UPDATED_METHOD = "thread/goal/updated";
6059
+ var THREAD_GOAL_CLEARED_METHOD = "thread/goal/cleared";
6060
+ var ITEM_STARTED_METHOD = "item/started";
6061
+ var ITEM_COMPLETED_METHOD = "item/completed";
6062
+ var AGENT_MESSAGE_DELTA_METHOD = "item/agentMessage/delta";
6063
+ var REASONING_SUMMARY_TEXT_DELTA_METHOD = "item/reasoning/summaryTextDelta";
6064
+ var REASONING_TEXT_DELTA_METHOD = "item/reasoning/textDelta";
6065
+ var REASONING_SUMMARY_PART_ADDED_METHOD = "item/reasoning/summaryPartAdded";
6066
+ var COMMAND_EXECUTION_OUTPUT_DELTA_METHOD = "item/commandExecution/outputDelta";
6067
+ var FILE_CHANGE_OUTPUT_DELTA_METHOD = "item/fileChange/outputDelta";
6068
+ var ACCOUNT_RATE_LIMITS_UPDATED_METHOD = "account/rateLimits/updated";
6069
+ var THREAD_TOKEN_USAGE_UPDATED_METHOD = "thread/tokenUsage/updated";
6070
+ var THREAD_COMPACTED_METHOD = "thread/compacted";
6071
+ function dispatchAspNotification(notification, handlers) {
6072
+ const handler = handlers[notification.method];
6073
+ if (!handler) return;
6074
+ handler(notification);
6075
+ }
6076
+ function recoverCompletedTurn(turn, completedItems, agentMessageDeltas) {
6077
+ const items = turn.items.length > 0 ? [...turn.items] : [];
6078
+ const itemIds = new Set(items.map((item) => item.id));
6079
+ for (const item of completedItems) {
6080
+ if (itemIds.has(item.id)) continue;
6081
+ items.push(item);
6082
+ itemIds.add(item.id);
6083
+ }
6084
+ for (const [itemId, text] of agentMessageDeltas) {
6085
+ if (itemIds.has(itemId)) continue;
6086
+ items.push({ type: "agentMessage", id: itemId, text, phase: null, memoryCitation: null });
6087
+ }
6088
+ return items.length > 0 ? { ...turn, items, itemsView: "full" } : turn;
6089
+ }
6090
+
6240
6091
  export {
6241
6092
  isRecord,
6242
6093
  TIMEOUT,
@@ -6249,6 +6100,7 @@ export {
6249
6100
  VALID_THINKING_LEVELS,
6250
6101
  codexReasoningEffortForThinkingLevel,
6251
6102
  detectAgentQuotaLimit,
6103
+ agentCredentialSnapshotSchema,
6252
6104
  isAgentChatTurnActivityRecord,
6253
6105
  isAgentChatSkillActivityRecord,
6254
6106
  isAgentChatMcpActivityRecord,
@@ -6277,6 +6129,9 @@ export {
6277
6129
  CLAUDE_HAIKU_4_5_MODEL,
6278
6130
  CLAUDE_FABLE_5_BEDROCK_MODEL,
6279
6131
  CLAUDE_OPUS_5_BEDROCK_MODEL,
6132
+ CLAUDE_OPUS_4_8_BEDROCK_MODEL,
6133
+ CLAUDE_SONNET_5_BEDROCK_MODEL,
6134
+ CLAUDE_HAIKU_4_5_BEDROCK_MODEL,
6280
6135
  DEFAULT_CLAUDE_MODEL,
6281
6136
  DEFAULT_CODEX_MODEL,
6282
6137
  DEFAULT_CURSOR_MODEL,
@@ -6301,7 +6156,10 @@ export {
6301
6156
  clampTokensToWindow,
6302
6157
  buildCodexTokenUsageContextUsagePayload,
6303
6158
  SANDBOX_PATHS,
6159
+ REPLICAS_RUNTIME_ENV_ALIASES,
6160
+ readReplicasRuntimeEnv,
6304
6161
  shellQuotePosix,
6162
+ parsePosixEnvFile,
6305
6163
  GIT_CREDENTIAL_HELPER_FILENAME,
6306
6164
  GITHUB_CREDENTIAL_REFRESH_PATH,
6307
6165
  GITLAB_CREDENTIAL_REFRESH_PATH,
@@ -6382,14 +6240,27 @@ export {
6382
6240
  isUnsafeMemoryOutput,
6383
6241
  isSkillRegistryManifest,
6384
6242
  putPresignedFile,
6385
- isRecord4 as isRecord2,
6386
- IS_WARMING_MODE,
6387
- ENGINE_ENV,
6388
- setAgentCredentialSnapshot,
6389
- resolveClaudeAuthMethodForMessage,
6390
- buildClaudeAgentEnv,
6243
+ buildCodexAgentEnv,
6391
6244
  execAsync,
6392
6245
  execFileAsync,
6393
6246
  SUBPROCESS_MAX_BUFFER,
6394
- AppServerProcess
6247
+ AppServerProcess,
6248
+ TURN_STARTED_METHOD,
6249
+ TURN_COMPLETED_METHOD,
6250
+ TURN_PLAN_UPDATED_METHOD,
6251
+ THREAD_GOAL_UPDATED_METHOD,
6252
+ THREAD_GOAL_CLEARED_METHOD,
6253
+ ITEM_STARTED_METHOD,
6254
+ ITEM_COMPLETED_METHOD,
6255
+ AGENT_MESSAGE_DELTA_METHOD,
6256
+ REASONING_SUMMARY_TEXT_DELTA_METHOD,
6257
+ REASONING_TEXT_DELTA_METHOD,
6258
+ REASONING_SUMMARY_PART_ADDED_METHOD,
6259
+ COMMAND_EXECUTION_OUTPUT_DELTA_METHOD,
6260
+ FILE_CHANGE_OUTPUT_DELTA_METHOD,
6261
+ ACCOUNT_RATE_LIMITS_UPDATED_METHOD,
6262
+ THREAD_TOKEN_USAGE_UPDATED_METHOD,
6263
+ THREAD_COMPACTED_METHOD,
6264
+ dispatchAspNotification,
6265
+ recoverCompletedTurn
6395
6266
  };
@@ -2,10 +2,12 @@
2
2
  import {
3
3
  AGENT,
4
4
  AppServerProcess,
5
+ buildCodexAgentEnv,
5
6
  headlessAgentRequestSchema,
6
7
  isUnsafeMemoryOutput,
7
- putPresignedFile
8
- } from "./chunk-3CX4NHQA.js";
8
+ putPresignedFile,
9
+ recoverCompletedTurn
10
+ } from "./chunk-ESC6QHTZ.js";
9
11
 
10
12
  // src/headless-agent.ts
11
13
  import { createHash } from "crypto";
@@ -120,15 +122,32 @@ async function runClaude(request) {
120
122
  }
121
123
  function runCodexTurn(client, params, timeoutMs) {
122
124
  return new Promise((resolve, reject) => {
125
+ const completedItems = [];
126
+ const messageDeltas = /* @__PURE__ */ new Map();
123
127
  const cleanup = () => {
124
128
  clearTimeout(timeout);
125
129
  client.off("notification", onNotification);
126
130
  client.off("dispose", onDispose);
127
131
  };
128
132
  const onNotification = (notification) => {
133
+ if (notification.method === "item/completed") {
134
+ if (notification.params.threadId !== params.threadId || notification.params.item.type !== "agentMessage") return;
135
+ completedItems.push(notification.params.item);
136
+ return;
137
+ }
138
+ if (notification.method === "item/agentMessage/delta") {
139
+ if (notification.params.threadId !== params.threadId) return;
140
+ messageDeltas.set(
141
+ notification.params.itemId,
142
+ (messageDeltas.get(notification.params.itemId) ?? "") + notification.params.delta
143
+ );
144
+ return;
145
+ }
129
146
  if (notification.method !== "turn/completed" || notification.params.threadId !== params.threadId) return;
147
+ const turn = recoverCompletedTurn(notification.params.turn, completedItems, messageDeltas);
148
+ const message = turn.items.findLast((item) => item.type === "agentMessage")?.text ?? null;
130
149
  cleanup();
131
- resolve(notification.params.turn);
150
+ resolve({ turn, message });
132
151
  };
133
152
  const onDispose = (error) => {
134
153
  cleanup();
@@ -149,6 +168,7 @@ function runCodexTurn(client, params, timeoutMs) {
149
168
  async function runCodex(request) {
150
169
  const appServer = new AppServerProcess({
151
170
  cwd: request.workingDirectory,
171
+ env: buildCodexAgentEnv(),
152
172
  configOverrides: ["shell_environment_policy.inherit=none", "tools.web_search=false"]
153
173
  });
154
174
  try {
@@ -167,7 +187,7 @@ async function runCodex(request) {
167
187
  dynamicTools: [],
168
188
  selectedCapabilityRoots: []
169
189
  });
170
- const turn = await runCodexTurn(client, {
190
+ const { turn, message } = await runCodexTurn(client, {
171
191
  threadId: thread.thread.id,
172
192
  input: [{ type: "text", text: request.prompt, text_elements: [] }],
173
193
  ...request.mode === "structured" ? { outputSchema: request.outputSchema } : {},
@@ -176,10 +196,9 @@ async function runCodex(request) {
176
196
  environments: []
177
197
  }, request.timeoutSeconds * 1e3);
178
198
  if (turn.status === "failed") throw new Error(turn.error?.message ?? "Codex ASP turn failed");
179
- const message = turn.items.findLast((item) => item.type === "agentMessage");
180
- if (!message || message.type !== "agentMessage") throw new Error("Codex ASP returned no final message");
181
- if (request.mode === "filesystem") return message.text;
182
- return JSON.parse(message.text);
199
+ if (!message) throw new Error("Codex ASP returned no final message");
200
+ if (request.mode === "filesystem") return message;
201
+ return JSON.parse(message);
183
202
  } finally {
184
203
  await appServer.stop();
185
204
  }