orkestrator 2.34.4-beta → 2.35.0-beta

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.
@@ -331,7 +331,7 @@ function createBridgeDiagnostics(bridge, state, metrics) {
331
331
  import { execFile as execFileCallback2 } from "node:child_process";
332
332
  import { randomBytes, timingSafeEqual } from "node:crypto";
333
333
  import { appendFile as appendFile5, mkdir as mkdir9, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
334
- import { join as join21 } from "node:path";
334
+ import { join as join22 } from "node:path";
335
335
  import { promisify as promisify2 } from "node:util";
336
336
 
337
337
  // ../../node_modules/.bun/@hono+node-server@2.1.5+c539cad7f494f5c9/node_modules/@hono/node-server/dist/constants-BLSFu_RU.mjs
@@ -3752,6 +3752,66 @@ function structuredOutputFailure(provider, code, message, options = {}) {
3752
3752
  };
3753
3753
  }
3754
3754
 
3755
+ // ../protocol/src/agent-platforms.ts
3756
+ var AGENT_PLATFORMS = Object.freeze([
3757
+ "claude",
3758
+ "codex",
3759
+ "cursor",
3760
+ "grok",
3761
+ "opencode",
3762
+ "pi"
3763
+ ]);
3764
+ var AGENT_PLATFORM_LABELS = Object.freeze({
3765
+ claude: "Claude Code",
3766
+ codex: "Codex",
3767
+ cursor: "Cursor Agent",
3768
+ grok: "Grok Build",
3769
+ opencode: "OpenCode",
3770
+ pi: "Pi"
3771
+ });
3772
+ var LEGACY_ENABLED_AGENT_PLATFORMS = Object.freeze([
3773
+ "claude",
3774
+ "codex",
3775
+ "opencode"
3776
+ ]);
3777
+
3778
+ // ../protocol/src/native-agent-goal.ts
3779
+ var NATIVE_AGENT_GOAL_LIMITS = Object.freeze({
3780
+ objectiveMaxChars: 4000,
3781
+ checkMaxBytes: 4 * 1024,
3782
+ reportMessageMaxBytes: 2 * 1024,
3783
+ checkOutputMaxBytes: 8 * 1024,
3784
+ statusDetailMaxBytes: 1024,
3785
+ maxIterationsDefault: 20,
3786
+ maxIterationsLimit: 100,
3787
+ noProgressLimit: 3,
3788
+ checkTimeoutDefaultMs: 10 * 60000,
3789
+ checkTimeoutMaxMs: 30 * 60000,
3790
+ verifierModelMaxChars: 200,
3791
+ verifierTimeoutDefaultMs: 30 * 60000,
3792
+ verdictSummaryMaxBytes: 2 * 1024,
3793
+ verdictReasonsMax: 16,
3794
+ verdictReasonMaxBytes: 512,
3795
+ historyLimit: 5
3796
+ });
3797
+ var AGENT_GOAL_TOOL_NAMES = Object.freeze(["report_goal"]);
3798
+ var GOAL_QUALIFIED_PLATFORMS = Object.freeze([
3799
+ "claude",
3800
+ "codex",
3801
+ "opencode",
3802
+ "cursor",
3803
+ "grok",
3804
+ "pi"
3805
+ ]);
3806
+ var GOAL_TOKEN_BUDGET_PLATFORMS = Object.freeze([
3807
+ "claude",
3808
+ "codex",
3809
+ "opencode",
3810
+ "cursor",
3811
+ "grok",
3812
+ "pi"
3813
+ ]);
3814
+
3755
3815
  // ../protocol/src/permission-rules.ts
3756
3816
  var PERMISSION_RULE_KINDS = [
3757
3817
  "command-prefix",
@@ -4153,29 +4213,6 @@ var JOURNAL_ENVELOPE_BYTES = serializedBytes({
4153
4213
  entries: []
4154
4214
  });
4155
4215
 
4156
- // ../protocol/src/agent-platforms.ts
4157
- var AGENT_PLATFORMS = Object.freeze([
4158
- "claude",
4159
- "codex",
4160
- "cursor",
4161
- "grok",
4162
- "opencode",
4163
- "pi"
4164
- ]);
4165
- var AGENT_PLATFORM_LABELS = Object.freeze({
4166
- claude: "Claude Code",
4167
- codex: "Codex",
4168
- cursor: "Cursor Agent",
4169
- grok: "Grok Build",
4170
- opencode: "OpenCode",
4171
- pi: "Pi"
4172
- });
4173
- var LEGACY_ENABLED_AGENT_PLATFORMS = Object.freeze([
4174
- "claude",
4175
- "codex",
4176
- "opencode"
4177
- ]);
4178
-
4179
4216
  // ../protocol/src/native-agent-transcript-patch.ts
4180
4217
  var FORBIDDEN_KEYS = new Set(["__proto__", "constructor", "prototype"]);
4181
4218
 
@@ -4542,6 +4579,7 @@ var PROJECTION_FIELD_SET = new Set([
4542
4579
  "queue",
4543
4580
  "asyncQuestionResponses",
4544
4581
  "contextUsage",
4582
+ "goal",
4545
4583
  "rateLimits",
4546
4584
  "runtime",
4547
4585
  "runtimeHealthAuthoritative",
@@ -4566,6 +4604,7 @@ var OPTIONAL_PROJECTION_FIELD_SET = new Set([
4566
4604
  "queue",
4567
4605
  "asyncQuestionResponses",
4568
4606
  "contextUsage",
4607
+ "goal",
4569
4608
  "rateLimits",
4570
4609
  "runtime",
4571
4610
  "runtimeHealthAuthoritative",
@@ -5522,7 +5561,7 @@ function parseSessionActivityObservation(value) {
5522
5561
  if (!isRecord(value))
5523
5562
  return;
5524
5563
  const { activity, readyForInput, completionPending, asyncQuestionItemIds, closing } = value;
5525
- const { contentRevision } = value;
5564
+ const { contentRevision, turnFailed } = value;
5526
5565
  if (typeof activity !== "string" || !SESSION_ACTIVITY_STATES.has(activity))
5527
5566
  return;
5528
5567
  if (readyForInput !== undefined && typeof readyForInput !== "boolean")
@@ -5531,6 +5570,8 @@ function parseSessionActivityObservation(value) {
5531
5570
  return;
5532
5571
  if (closing !== undefined && typeof closing !== "boolean")
5533
5572
  return;
5573
+ if (turnFailed !== undefined && typeof turnFailed !== "boolean")
5574
+ return;
5534
5575
  if (contentRevision !== undefined && !isContentRevision(contentRevision))
5535
5576
  return;
5536
5577
  let itemIds;
@@ -5546,6 +5587,7 @@ function parseSessionActivityObservation(value) {
5546
5587
  ...completionPending !== undefined ? { completionPending } : {},
5547
5588
  ...itemIds !== undefined ? { asyncQuestionItemIds: itemIds } : {},
5548
5589
  ...closing !== undefined ? { closing } : {},
5590
+ ...turnFailed === true ? { turnFailed } : {},
5549
5591
  ...contentRevision !== undefined ? { contentRevision } : {}
5550
5592
  };
5551
5593
  }
@@ -12074,6 +12116,7 @@ function unconfirmedTurnId(requestId) {
12074
12116
  class TurnAccumulator {
12075
12117
  threadId;
12076
12118
  requestId;
12119
+ providerRequestId;
12077
12120
  expectsStructuredOutput;
12078
12121
  assistantMessageId;
12079
12122
  startedAt;
@@ -12083,6 +12126,7 @@ class TurnAccumulator {
12083
12126
  phase = "starting";
12084
12127
  cancelRequested = false;
12085
12128
  stoppedByShutdown = false;
12129
+ capacityRetry;
12086
12130
  error;
12087
12131
  finalDiff;
12088
12132
  completedAt;
@@ -12362,12 +12406,22 @@ class TurnAccumulator {
12362
12406
  if (error)
12363
12407
  this.error = error;
12364
12408
  this.completedAt = new Date().toISOString();
12409
+ this.settleEndedAttempt();
12410
+ }
12411
+ settleEndedAttempt() {
12365
12412
  this.interruptOpenAgentMessages();
12366
12413
  for (const accumulator of this.items.values()) {
12367
12414
  if (!accumulator.completed && !accumulator.interrupted)
12368
12415
  this.touch(accumulator);
12369
12416
  }
12370
12417
  }
12418
+ recordRetryCard(id, text, state) {
12419
+ this.onItemCompleted({ id, type: "retry", text, state });
12420
+ }
12421
+ retryCardState(id) {
12422
+ const item = this.items.get(id)?.item;
12423
+ return item?.type === "retry" ? item.state : undefined;
12424
+ }
12371
12425
  recordProviderFailure(error) {
12372
12426
  this.onItemCompleted({
12373
12427
  id: turnFailureItemId(this.turnId),
@@ -12820,6 +12874,8 @@ async function itemToParts(item, cwd, fileChangeContext) {
12820
12874
  ...item.severity ? { severity: item.severity } : {}
12821
12875
  }
12822
12876
  ];
12877
+ case "retry":
12878
+ return [{ type: "retry", content: item.text, toolState: item.state }];
12823
12879
  default: {
12824
12880
  const unknown = item;
12825
12881
  const name = typeof unknown.type === "string" ? unknown.type : "unknown";
@@ -13012,16 +13068,19 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
13012
13068
  "add_ticket_comment",
13013
13069
  "address_multi_review",
13014
13070
  "adopt_workflow",
13071
+ "answer_worker_question",
13015
13072
  "cancel_build_pipeline",
13016
13073
  "cancel_graph_run",
13017
13074
  "cancel_multi_review",
13018
13075
  "cancel_schedule",
13076
+ "clear_worker_goal",
13019
13077
  "compare_project_files",
13020
13078
  "create_pr",
13021
13079
  "create_schedule",
13022
13080
  "create_ticket",
13023
13081
  "custom_fix_multi_review",
13024
13082
  "edit_worker_tab",
13083
+ "fork_worker",
13025
13084
  "get_build_pipeline",
13026
13085
  "get_environment",
13027
13086
  "get_feature_plan",
@@ -13034,6 +13093,9 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
13034
13093
  "get_tab_state",
13035
13094
  "get_tab_transcript",
13036
13095
  "get_ticket",
13096
+ "get_usage_limits",
13097
+ "get_worker_changes",
13098
+ "get_worker_goal",
13037
13099
  "launch_environment",
13038
13100
  "launch_feature_plan",
13039
13101
  "launch_graph",
@@ -13048,14 +13110,18 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
13048
13110
  "list_node_environments",
13049
13111
  "list_nodes",
13050
13112
  "list_projects",
13113
+ "list_provider_accounts",
13051
13114
  "list_schedules",
13052
13115
  "list_tabs",
13053
13116
  "list_tickets",
13117
+ "list_worker_commands",
13054
13118
  "list_workflows",
13055
13119
  "open_multi_review",
13056
13120
  "open_multi_review_fix",
13057
13121
  "open_worker_browser",
13058
13122
  "pause_build_pipeline",
13123
+ "pause_schedule",
13124
+ "pause_worker_goal",
13059
13125
  "propose_agents_md_update",
13060
13126
  "read_messages",
13061
13127
  "read_node_environment",
@@ -13064,18 +13130,26 @@ var COORDINATOR_CONTROL_TOOL_NAMES = Object.freeze([
13064
13130
  "request_project_file_update",
13065
13131
  "request_project_on_node",
13066
13132
  "request_root_changes",
13133
+ "resolve_conflicts",
13067
13134
  "resume_build_pipeline",
13135
+ "resume_schedule",
13136
+ "run_worker_command",
13068
13137
  "send_message",
13069
13138
  "send_node_message",
13070
13139
  "send_prompt_to_node_tab",
13071
13140
  "send_prompt_to_tab",
13141
+ "set_worker_goal",
13072
13142
  "start_build_pipeline",
13073
13143
  "start_environment",
13074
13144
  "start_multi_review",
13075
13145
  "start_node_environment",
13076
13146
  "stop_environment",
13077
13147
  "stop_node_environment",
13148
+ "stop_worker_turn",
13149
+ "switch_provider_account",
13150
+ "set_account_auto_switch",
13078
13151
  "transfer_files",
13152
+ "update_schedule",
13079
13153
  "update_ticket"
13080
13154
  ]);
13081
13155
  var COORDINATOR_CONTEXT_OPEN_TAG = "<orkestrator-coordinator-context>";
@@ -13089,6 +13163,78 @@ function stripCoordinatorContext(text) {
13089
13163
  return text.slice(end + COORDINATOR_CONTEXT_CLOSE_TAG.length).replace(/^\s+/, "");
13090
13164
  }
13091
13165
 
13166
+ // ../protocol/src/capacity-retry.ts
13167
+ var DEFAULT_CAPACITY_RETRY_POLICY = {
13168
+ maxAttempts: 5,
13169
+ baseDelayMs: 2000,
13170
+ multiplier: 3,
13171
+ maxDelayMs: 60000
13172
+ };
13173
+ function capacityRetryDelayMs(policy, nextAttempt, random = Math.random) {
13174
+ const retryIndex = Math.max(0, nextAttempt - 2);
13175
+ const nominal = Math.min(policy.maxDelayMs, policy.baseDelayMs * policy.multiplier ** retryIndex);
13176
+ const unit = Math.min(1, Math.max(0, random()));
13177
+ return Math.round(nominal / 2 + nominal / 2 * unit);
13178
+ }
13179
+ function formatRetryDelay(delayMs) {
13180
+ return `${Math.max(1, Math.round(delayMs / 1000))} s`;
13181
+ }
13182
+
13183
+ // ../../bridges/codex-bridge/src/sessions/capacity-retry.ts
13184
+ var CODEX_SERVER_OVERLOADED_MESSAGE = "Selected model is at capacity. Please try a different model.";
13185
+ var CODEX_POLICY_CAPACITY_UNAVAILABLE_MESSAGE = "Policy-restricted capacity is unavailable. Please try again later.";
13186
+ var CAPACITY_CODES = new Set(["serverOverloaded", "policyCapacityUnavailable"]);
13187
+ var CAPACITY_MESSAGES = new Set([
13188
+ CODEX_SERVER_OVERLOADED_MESSAGE,
13189
+ CODEX_POLICY_CAPACITY_UNAVAILABLE_MESSAGE
13190
+ ]);
13191
+ function isModelCapacityError(error) {
13192
+ if (!error)
13193
+ return false;
13194
+ if (error.httpStatusCode === 401 || error.httpStatusCode === 403)
13195
+ return false;
13196
+ if (error.code !== undefined)
13197
+ return CAPACITY_CODES.has(error.code);
13198
+ return CAPACITY_MESSAGES.has(error.message.trim());
13199
+ }
13200
+ function capacityRetryWaitingText(delayMs, nextAttempt, maxAttempts) {
13201
+ return `Model at capacity, retrying in ${formatRetryDelay(delayMs)} (attempt ${nextAttempt} of ${maxAttempts})`;
13202
+ }
13203
+ function capacityRetryStartedText(nextAttempt, maxAttempts) {
13204
+ return `Model at capacity, retried automatically (attempt ${nextAttempt} of ${maxAttempts})`;
13205
+ }
13206
+ var CAPACITY_RETRY_CANCELLED_TEXT = "Model at capacity, automatic retry cancelled";
13207
+ var CAPACITY_RETRY_START_FAILED_TEXT = "Model at capacity, automatic retry could not be started";
13208
+ function capacityRetriesExhaustedError(error, attempts) {
13209
+ return {
13210
+ ...error,
13211
+ message: `${error.message} Automatic retries exhausted after ${attempts} attempts.`
13212
+ };
13213
+ }
13214
+ function capacityRetryItemId(requestId, nextAttempt) {
13215
+ return `capacity-retry:${requestId}:${nextAttempt}`;
13216
+ }
13217
+ function capacityRetryClientId(requestId, nextAttempt) {
13218
+ return `${requestId}:capacity-retry:${nextAttempt}`;
13219
+ }
13220
+ var CAPACITY_RETRY_CONTINUATION_MARKER = "[Orkestrator automatic retry]";
13221
+ function capacityRetryContinuationText(nextAttempt, maxAttempts) {
13222
+ return [
13223
+ `${CAPACITY_RETRY_CONTINUATION_MARKER} attempt ${nextAttempt} of ${maxAttempts}.`,
13224
+ "The previous attempt of this turn ended because the model was at capacity. This message was sent automatically, not by the user.",
13225
+ "Continue the original request from where it stopped. Do not repeat work or tool calls that already completed; check the conversation so far and finish the request."
13226
+ ].join(`
13227
+ `);
13228
+ }
13229
+ function parseCapacityRetryContinuation(text) {
13230
+ if (!text.startsWith(CAPACITY_RETRY_CONTINUATION_MARKER))
13231
+ return;
13232
+ const match = /^ attempt (\d+) of (\d+)\./.exec(text.slice(CAPACITY_RETRY_CONTINUATION_MARKER.length));
13233
+ if (!match)
13234
+ return;
13235
+ return { attempt: Number(match[1]), maxAttempts: Number(match[2]) };
13236
+ }
13237
+
13092
13238
  // ../../bridges/codex-bridge/src/history/rollout.ts
13093
13239
  function getCodexHomeDir() {
13094
13240
  return process.env.CODEX_HOME || join11(homedir(), ".codex");
@@ -14126,6 +14272,20 @@ async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns)
14126
14272
  assistantMessage.parts.push({ type: "text", content: displayText });
14127
14273
  return;
14128
14274
  }
14275
+ const continuation = parseCapacityRetryContinuation(text);
14276
+ if (continuation) {
14277
+ const previous = messages.at(-1);
14278
+ const row = previous?.role === "assistant" ? previous : ensureAssistantMessage(timestamp);
14279
+ const last = row.parts.at(-1);
14280
+ if (last?.type === "status" && last.severity === "error")
14281
+ row.parts.pop();
14282
+ row.parts.push({
14283
+ type: "retry",
14284
+ content: capacityRetryStartedText(continuation.attempt, continuation.maxAttempts),
14285
+ toolState: "success"
14286
+ });
14287
+ return;
14288
+ }
14129
14289
  closeAssistantRow();
14130
14290
  messages.push({
14131
14291
  id: nextRowId("user"),
@@ -14994,6 +15154,87 @@ function agentMailCapabilities(tabType, agent, locked = true) {
14994
15154
  }
14995
15155
  var NATIVE_AGENT_MAIL_CAPABILITIES = Object.freeze(Object.fromEntries(AGENT_PLATFORMS.map((agent) => [agent, agentMailCapabilities("agent-native", agent)])));
14996
15156
 
15157
+ // ../protocol/src/agent-system-instructions.ts
15158
+ var AGENT_IMAGE_PREVIEW_INSTRUCTION = "Orkestrator renders Markdown images inline in the transcript. When you show the user an image in your reply (a screenshot, rendered preview, or chart) using Markdown image syntax, reference it by its absolute path. In a managed worktree or container environment, save the file inside the working directory, preferably in a git-ignored folder so preview files stay out of the change set. Local image previews are limited to Orkestrator-managed workspace storage or the container's /workspace. Project-home checkouts are excluded from host preview reads, even when they are the working directory, so images saved there cannot be previewed from a local Markdown path. Paths outside previewable storage, such as /tmp, also show a placeholder.";
15159
+ var AGENT_DOCUMENT_INSTRUCTION = "When the user asks for a document (a report, design doc, plan, analysis, guide, or other writing to keep), prefer writing it as a Markdown file in a `docs/` folder at the root of the working directory, and tell the user the file's path. Project instructions (such as AGENTS.md or CLAUDE.md), local skills, and the user's own request take priority over this default when they say where or how to write documents.";
15160
+ var GENERAL_AGENT_INSTRUCTIONS = [
15161
+ AGENT_IMAGE_PREVIEW_INSTRUCTION,
15162
+ AGENT_DOCUMENT_INSTRUCTION
15163
+ ];
15164
+ function agentSystemInstructions(providerSpecific = []) {
15165
+ return [...GENERAL_AGENT_INSTRUCTIONS, ...providerSpecific].filter((line) => line.trim().length > 0).join(`
15166
+
15167
+ `);
15168
+ }
15169
+ var REPOSITORY_INSTRUCTIONS_FILE = "AGENTS.md";
15170
+ function repositoryInstructionsBlock(path, content, truncated) {
15171
+ return [
15172
+ `# Repository instructions (${REPOSITORY_INSTRUCTIONS_FILE})`,
15173
+ `This session does not load the repository's ${REPOSITORY_INSTRUCTIONS_FILE} on its own, so Orkestrator includes it here. Follow it as project instructions. Contents of ${path}:`,
15174
+ content.trimEnd(),
15175
+ ...truncated ? [
15176
+ `[${REPOSITORY_INSTRUCTIONS_FILE} is longer than this session can hold, so it is cut here. Read the rest from ${path} before relying on anything it may say.]`
15177
+ ] : []
15178
+ ].join(`
15179
+
15180
+ `);
15181
+ }
15182
+
15183
+ // ../protocol/src/node/repository-instructions.ts
15184
+ import { open as open4, realpath } from "node:fs/promises";
15185
+ import { join as join12, relative as relative2, isAbsolute as isAbsolute7 } from "node:path";
15186
+ var MAX_REPOSITORY_INSTRUCTIONS_BYTES = 256 * 1024;
15187
+ async function readRepositoryInstructions(cwd, maxBytes = MAX_REPOSITORY_INSTRUCTIONS_BYTES) {
15188
+ const path = join12(cwd, REPOSITORY_INSTRUCTIONS_FILE);
15189
+ try {
15190
+ const [root, target] = await Promise.all([realpath(cwd), realpath(path)]);
15191
+ const inside = relative2(root, target);
15192
+ if (!inside || inside.startsWith("..") || isAbsolute7(inside))
15193
+ return;
15194
+ const handle = await open4(target, "r");
15195
+ try {
15196
+ const buffer = Buffer.alloc(maxBytes + 1);
15197
+ const { bytesRead } = await handle.read(buffer, 0, maxBytes + 1, 0);
15198
+ const truncated = bytesRead > maxBytes;
15199
+ const text = new TextDecoder().decode(buffer.subarray(0, Math.min(bytesRead, maxBytes))).replace(/�$/, "");
15200
+ return text.trim() ? repositoryInstructionsBlock(path, text, truncated) : undefined;
15201
+ } finally {
15202
+ await handle.close();
15203
+ }
15204
+ } catch {
15205
+ return;
15206
+ }
15207
+ }
15208
+
15209
+ // ../protocol/src/build-pipeline-key-information.ts
15210
+ var KEY_INFORMATION_LIMITS = Object.freeze({
15211
+ proseLength: 4000,
15212
+ itemLength: 600,
15213
+ listItems: 30,
15214
+ decisions: 12,
15215
+ decisionLength: 400,
15216
+ options: 6,
15217
+ optionLength: 300,
15218
+ prosCons: 6,
15219
+ rationaleLength: 1000,
15220
+ tests: 40,
15221
+ testNameLength: 400,
15222
+ issues: 60,
15223
+ issueLength: 400,
15224
+ severityLength: 40,
15225
+ resolutionLength: 1000,
15226
+ verifications: 20,
15227
+ summaryLength: 2000,
15228
+ checks: 30,
15229
+ checkLength: 400,
15230
+ updates: 30,
15231
+ maxRound: 1000
15232
+ });
15233
+ var KEY_INFORMATION_TOOL_NAMES = Object.freeze([
15234
+ "get_key_information",
15235
+ "update_key_information"
15236
+ ]);
15237
+
14997
15238
  // ../protocol/src/transcript-artifacts.ts
14998
15239
  var ARTIFACT_TOOL_NAMES = Object.freeze([
14999
15240
  "create_artifact",
@@ -15008,9 +15249,9 @@ var ORKESTRATOR_ARTIFACT_MCP_SERVER_NAME = "orkestrator-artifacts";
15008
15249
  var ORKESTRATOR_ARTIFACT_MCP_PATH = "/artifact-mcp";
15009
15250
 
15010
15251
  // ../../bridges/codex-bridge/src/engine/app-server-engine.ts
15011
- import { open as open7 } from "node:fs/promises";
15252
+ import { open as open8 } from "node:fs/promises";
15012
15253
  import { createHash as createHash11 } from "node:crypto";
15013
- import { isAbsolute as isAbsolute8, join as join18 } from "node:path";
15254
+ import { isAbsolute as isAbsolute9, join as join19 } from "node:path";
15014
15255
 
15015
15256
  // ../../bridges/codex-bridge/src/app-server/process-supervisor.ts
15016
15257
  import { execFile as execFile3, spawn as spawn2 } from "node:child_process";
@@ -15018,14 +15259,14 @@ import { randomUUID as randomUUID6 } from "node:crypto";
15018
15259
  import {
15019
15260
  link,
15020
15261
  mkdir as mkdir6,
15021
- open as open4,
15262
+ open as open5,
15022
15263
  readFile as readFile5,
15023
15264
  readlink,
15024
15265
  rename as rename4,
15025
15266
  rm as rm5,
15026
15267
  stat as stat5
15027
15268
  } from "node:fs/promises";
15028
- import { join as join13 } from "node:path";
15269
+ import { join as join14 } from "node:path";
15029
15270
 
15030
15271
  // ../../bridges/codex-bridge/src/app-server/errors.ts
15031
15272
  var APP_SERVER_OVERLOAD_CODE = -32001;
@@ -15625,7 +15866,7 @@ class SerialQueue {
15625
15866
 
15626
15867
  // ../../bridges/codex-bridge/src/app-server/notification-recorder.ts
15627
15868
  import { appendFile as appendFile4, mkdir as mkdir5 } from "node:fs/promises";
15628
- import { join as join12 } from "node:path";
15869
+ import { join as join13 } from "node:path";
15629
15870
  var DEFAULT_MAX_RECORDING_BYTES = 64 * 1024 * 1024;
15630
15871
  var DEFAULT_FLUSH_INTERVAL_MS = 250;
15631
15872
  var DEFAULT_WARN_INTERVAL_MS = 60000;
@@ -15651,7 +15892,7 @@ class NotificationRecorder {
15651
15892
  stats;
15652
15893
  constructor(options) {
15653
15894
  this.options = options;
15654
- this.path = join12(options.directory, options.fileName);
15895
+ this.path = join13(options.directory, options.fileName);
15655
15896
  this.maxBytes = options.maxBytes ?? DEFAULT_MAX_RECORDING_BYTES;
15656
15897
  this.flushIntervalMs = options.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS;
15657
15898
  this.warnIntervalMs = options.warnIntervalMs ?? DEFAULT_WARN_INTERVAL_MS;
@@ -16378,10 +16619,10 @@ class AppServerSupervisor {
16378
16619
  } catch {}
16379
16620
  }
16380
16621
  pidFileDir() {
16381
- return join13(this.options.codexHome, "orkestrator-bridge");
16622
+ return join14(this.options.codexHome, "orkestrator-bridge");
16382
16623
  }
16383
16624
  pidFilePath() {
16384
- return join13(this.pidFileDir(), `app-server-${hashPath(this.options.cwd)}.pid`);
16625
+ return join14(this.pidFileDir(), `app-server-${hashPath(this.options.cwd)}.pid`);
16385
16626
  }
16386
16627
  async readOwnedPidRecord(path) {
16387
16628
  let raw;
@@ -16420,7 +16661,7 @@ class AppServerSupervisor {
16420
16661
  instanceId
16421
16662
  }), "utf8");
16422
16663
  const temporary = `${path}.${this.pidOwnerToken}.update`;
16423
- const handle = await open4(temporary, "wx", 384);
16664
+ const handle = await open5(temporary, "wx", 384);
16424
16665
  try {
16425
16666
  await handle.write(payload, 0, payload.length, 0);
16426
16667
  await handle.sync();
@@ -16444,7 +16685,7 @@ class AppServerSupervisor {
16444
16685
  await mkdir6(this.pidFileDir(), { recursive: true });
16445
16686
  for (let attempt = 0;attempt < PID_ACQUISITION_MAX_ATTEMPTS; attempt += 1) {
16446
16687
  try {
16447
- const handle = await open4(this.pidFilePath(), "wx", 384);
16688
+ const handle = await open5(this.pidFilePath(), "wx", 384);
16448
16689
  try {
16449
16690
  const record = {
16450
16691
  ownerToken: this.pidOwnerToken,
@@ -16874,10 +17115,11 @@ function describeApproval(options) {
16874
17115
  } : undefined;
16875
17116
  const networkContext = isRecord9(params.networkApprovalContext) ? str2(params.networkApprovalContext.host) : undefined;
16876
17117
  const command = commandText(params.command) ?? commandActionsText(params.commandActions);
16877
- const exactCommand = options.method === "item/commandExecution/requestApproval" && (params.kind === undefined || params.kind === null || params.kind === "command") && typeof params.command === "string" && params.command.length > 0;
16878
- const ruleEligible = networkContext !== undefined ? kind === "command" && exactCommand : kind === "command" ? exactCommand : kind === "file-change" ? str2(params.grantRoot) === undefined : false;
17118
+ const v2Command = options.method === "item/commandExecution/requestApproval" && (params.kind === undefined || params.kind === null || params.kind === "command");
17119
+ const exactCommand = v2Command && typeof params.command === "string" && params.command.length > 0;
17120
+ const ruleEligible = networkContext !== undefined ? v2Command && (exactCommand || command === undefined) : kind === "command" ? exactCommand : kind === "file-change" ? str2(params.grantRoot) === undefined : false;
16879
17121
  const proposal = exactCommand ? proposedPrefix(params.proposedExecpolicyAmendment) : undefined;
16880
- const actionable = kind === "command" ? command !== undefined : kind === "file-change" ? Boolean(changes?.length) : permissions !== undefined && (permissions.network || permissions.fileSystem);
17122
+ const actionable = kind === "command" ? command !== undefined || networkContext !== undefined : kind === "file-change" ? Boolean(changes?.length) : permissions !== undefined && (permissions.network || permissions.fileSystem);
16881
17123
  return {
16882
17124
  approvalId: options.approvalId,
16883
17125
  kind,
@@ -16942,7 +17184,7 @@ function describeApprovalOutcome(request, decision, resolution) {
16942
17184
  return null;
16943
17185
  if (isGrantingApprovalDecision(decision))
16944
17186
  return null;
16945
- const subject = request.kind === "command" ? request.command ? `permission to run \`${request.command}\`` : "permission to run a command" : request.kind === "file-change" ? request.changes?.length ? `permission to change ${request.changes.length} file(s)` : "permission to apply a file change" : "additional permissions";
17187
+ const subject = request.kind === "command" ? request.command ? `permission to run \`${request.command}\`` : request.networkHost ? `permission to reach \`${request.networkHost}\`` : "permission to run a command" : request.kind === "file-change" ? request.changes?.length ? `permission to change ${request.changes.length} file(s)` : "permission to apply a file change" : "additional permissions";
16946
17188
  switch (resolution) {
16947
17189
  case "timed-out":
16948
17190
  return `Codex asked for ${subject}. The request expired without an answer, so it was declined.`;
@@ -17881,6 +18123,9 @@ function reduceNotification(notification, generation, handle) {
17881
18123
  if (!isRecord10(params) || !isRecord10(params.rateLimits))
17882
18124
  return { events: [] };
17883
18125
  const snapshot = params.rateLimits;
18126
+ const limitId = str3(snapshot.limitId);
18127
+ if (limitId && limitId !== "codex")
18128
+ return { events: [] };
17884
18129
  const windows = [];
17885
18130
  const limitName = typeof snapshot.limitName === "string" && snapshot.limitName.length > 0 ? snapshot.limitName : undefined;
17886
18131
  if (!isRecord10(snapshot.primary) && limitName !== undefined) {
@@ -18262,8 +18507,8 @@ function redactSecrets(value) {
18262
18507
 
18263
18508
  // ../../bridges/codex-bridge/src/sessions/dispatch-journal.ts
18264
18509
  import { createHash as createHash10 } from "node:crypto";
18265
- import { mkdir as mkdir8, open as open5, rename as rename6, rm as rm7, writeFile as writeFile5 } from "node:fs/promises";
18266
- import { join as join15 } from "node:path";
18510
+ import { mkdir as mkdir8, open as open6, rename as rename6, rm as rm7, writeFile as writeFile5 } from "node:fs/promises";
18511
+ import { join as join16 } from "node:path";
18267
18512
 
18268
18513
  // ../../bridges/codex-bridge/src/sessions/persistence.ts
18269
18514
  import { createHash as createHash9, randomUUID as randomUUID7 } from "node:crypto";
@@ -18278,7 +18523,7 @@ import {
18278
18523
  stat as stat6,
18279
18524
  writeFile as writeFile4
18280
18525
  } from "node:fs/promises";
18281
- import { join as join14 } from "node:path";
18526
+ import { join as join15 } from "node:path";
18282
18527
  var BRIDGE_SESSION_REGISTRY_VERSION = 2;
18283
18528
  var SESSION_TITLE_SOURCES = new Set([
18284
18529
  "codex",
@@ -18383,20 +18628,20 @@ class BridgeSessionStore {
18383
18628
  return codexBridgeStateDir(this.codexHome);
18384
18629
  }
18385
18630
  path() {
18386
- return join14(this.dir(), `bridge-sessions-${this.cwdHash}.json`);
18631
+ return join15(this.dir(), `bridge-sessions-${this.cwdHash}.json`);
18387
18632
  }
18388
18633
  recordsDir() {
18389
- return join14(this.dir(), `bridge-sessions-${this.cwdHash}`);
18634
+ return join15(this.dir(), `bridge-sessions-${this.cwdHash}`);
18390
18635
  }
18391
18636
  loginRecordsDir() {
18392
- const directory = join14(codexLoginBridgeDir(this.codexHome), `bridge-sessions-${this.cwdHash}`);
18637
+ const directory = join15(codexLoginBridgeDir(this.codexHome), `bridge-sessions-${this.cwdHash}`);
18393
18638
  return directory === this.recordsDir() ? undefined : directory;
18394
18639
  }
18395
18640
  recordKey(bridgeSessionId) {
18396
18641
  return createHash9("sha256").update(bridgeSessionId).digest("hex");
18397
18642
  }
18398
18643
  recordPath(bridgeSessionId) {
18399
- return join14(this.recordsDir(), `${this.recordKey(bridgeSessionId)}.json`);
18644
+ return join15(this.recordsDir(), `${this.recordKey(bridgeSessionId)}.json`);
18400
18645
  }
18401
18646
  async ensurePrivateStorage() {
18402
18647
  await mkdir7(this.dir(), { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
@@ -18424,7 +18669,7 @@ class BridgeSessionStore {
18424
18669
  return legacy;
18425
18670
  }
18426
18671
  const records = await Promise.all(names.map(async (name) => {
18427
- const path = join14(this.recordsDir(), name);
18672
+ const path = join15(this.recordsDir(), name);
18428
18673
  if (name.endsWith(".tmp")) {
18429
18674
  await chmod(path, PRIVATE_FILE_MODE).catch(() => {
18430
18675
  return;
@@ -18536,8 +18781,8 @@ class BridgeSessionStore {
18536
18781
  return;
18537
18782
  await this.ensurePrivateStorage();
18538
18783
  await Promise.all(names.map(async (name) => {
18539
- const from = join14(source, name);
18540
- const target = join14(this.recordsDir(), name);
18784
+ const from = join15(source, name);
18785
+ const target = join15(this.recordsDir(), name);
18541
18786
  const temporary = `${target}.${process.pid}.${randomUUID7()}.tmp`;
18542
18787
  await writeFile4(temporary, await readFile6(from), { mode: PRIVATE_FILE_MODE });
18543
18788
  await chmod(temporary, PRIVATE_FILE_MODE);
@@ -18650,7 +18895,7 @@ function isPersistedRecord(value) {
18650
18895
  if (!value || typeof value !== "object")
18651
18896
  return false;
18652
18897
  const record = value;
18653
- if (typeof record.requestId !== "string" || record.requestId.length === 0 || typeof record.bridgeSessionId !== "string" || record.threadId !== null && typeof record.threadId !== "string" || !isOptionalString(record.turnId) || !DISPATCH_STATES.has(record.state) || !isTimestamp(record.createdAt) || !isTimestamp(record.updatedAt) || record.quarantined !== undefined && record.quarantined !== true) {
18898
+ if (typeof record.requestId !== "string" || record.requestId.length === 0 || typeof record.bridgeSessionId !== "string" || record.threadId !== null && typeof record.threadId !== "string" || !isOptionalString(record.turnId) || !isOptionalString(record.providerRequestId) || !DISPATCH_STATES.has(record.state) || !isTimestamp(record.createdAt) || !isTimestamp(record.updatedAt) || record.quarantined !== undefined && record.quarantined !== true) {
18654
18899
  return false;
18655
18900
  }
18656
18901
  if (record.state === "accepted") {
@@ -18696,7 +18941,7 @@ class DispatchJournal {
18696
18941
  this.persist = options.persist !== false;
18697
18942
  }
18698
18943
  path() {
18699
- return join15(codexBridgeStateDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
18944
+ return join16(codexBridgeStateDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
18700
18945
  }
18701
18946
  async load() {
18702
18947
  if (this.loaded)
@@ -18706,7 +18951,7 @@ class DispatchJournal {
18706
18951
  this.loadSettled = true;
18707
18952
  return;
18708
18953
  }
18709
- const legacy = join15(codexLoginBridgeDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
18954
+ const legacy = join16(codexLoginBridgeDir(this.codexHome), `dispatch-journal-${this.cwdHash}.json`);
18710
18955
  try {
18711
18956
  const hadCurrent = await this.loadPath(this.path());
18712
18957
  const mergedLegacy = legacy !== this.path() && await this.loadPath(legacy, true);
@@ -18782,7 +19027,7 @@ class DispatchJournal {
18782
19027
  return true;
18783
19028
  }
18784
19029
  async readBounded(path) {
18785
- const handle = await open5(path, "r");
19030
+ const handle = await open6(path, "r");
18786
19031
  try {
18787
19032
  const metadata = await handle.stat();
18788
19033
  if (!metadata.isFile() || metadata.size > this.maxBytes) {
@@ -18858,6 +19103,21 @@ class DispatchJournal {
18858
19103
  await this.flush({ failClosed: true });
18859
19104
  return record;
18860
19105
  }
19106
+ async markContinuation(requestId, providerRequestId) {
19107
+ if (this.integrityError)
19108
+ throw new DispatchJournalIntegrityError(this.integrityError);
19109
+ const existing = this.records.get(requestId);
19110
+ if (!existing || existing.quarantined) {
19111
+ throw new DispatchJournalIntegrityError(`Dispatch ${requestId} is unavailable`);
19112
+ }
19113
+ this.records.set(requestId, {
19114
+ ...existing,
19115
+ providerRequestId,
19116
+ updatedAt: new Date(this.now()).toISOString(),
19117
+ sequence: ++this.nextSequence
19118
+ });
19119
+ await this.flush({ failClosed: true });
19120
+ }
18861
19121
  async markAccepted(requestId, options) {
18862
19122
  if (this.integrityError)
18863
19123
  throw new DispatchJournalIntegrityError(this.integrityError);
@@ -18868,6 +19128,7 @@ class DispatchJournal {
18868
19128
  const timestamp = new Date(this.now()).toISOString();
18869
19129
  this.records.set(requestId, {
18870
19130
  requestId,
19131
+ providerRequestId: existing?.providerRequestId,
18871
19132
  bridgeSessionId: existing?.bridgeSessionId ?? "",
18872
19133
  threadId: options.threadId,
18873
19134
  turnId: options.turnId,
@@ -18887,6 +19148,7 @@ class DispatchJournal {
18887
19148
  const timestamp = new Date(this.now()).toISOString();
18888
19149
  this.records.set(requestId, {
18889
19150
  requestId,
19151
+ providerRequestId: existing?.providerRequestId,
18890
19152
  bridgeSessionId: existing?.bridgeSessionId ?? "",
18891
19153
  threadId: options.threadId ?? existing?.threadId ?? null,
18892
19154
  turnId: options.turnId ?? existing?.turnId,
@@ -18908,6 +19170,7 @@ class DispatchJournal {
18908
19170
  const timestamp = new Date(this.now()).toISOString();
18909
19171
  this.records.set(requestId, {
18910
19172
  requestId,
19173
+ providerRequestId: existing?.providerRequestId,
18911
19174
  bridgeSessionId: existing?.bridgeSessionId ?? "",
18912
19175
  threadId: existing?.threadId ?? null,
18913
19176
  state: "retryable",
@@ -19240,7 +19503,7 @@ function coordinatorCapabilityPolicy(mode) {
19240
19503
  // ../../bridges/codex-bridge/src/codex-config.ts
19241
19504
  import { existsSync as existsSync3, readdirSync as readdirSync3, realpathSync, statSync as statSync2 } from "node:fs";
19242
19505
  import { homedir as homedir2 } from "node:os";
19243
- import { isAbsolute as isAbsolute7, join as join16, relative as relative2, sep } from "node:path";
19506
+ import { isAbsolute as isAbsolute8, join as join17, relative as relative3, sep } from "node:path";
19244
19507
 
19245
19508
  // ../../bridges/codex-bridge/src/engine/mcp-tool-availability.ts
19246
19509
  var ORKESTRATOR_MCP_STARTUP_TIMEOUT_SEC = 15;
@@ -19326,7 +19589,7 @@ function codexNetworkDeniedConfig(policy) {
19326
19589
  };
19327
19590
  }
19328
19591
  function codexProjectTrustConfig(policy, cwd) {
19329
- if (!policy || policy.projectResources || !cwd || !isAbsolute7(cwd))
19592
+ if (!policy || policy.projectResources || !cwd || !isAbsolute8(cwd))
19330
19593
  return {};
19331
19594
  const roots = new Set([cwd]);
19332
19595
  try {
@@ -19351,20 +19614,20 @@ function codexCoordinatorSkillExtraRoots(env = process.env, cwd = env.CWD?.trim(
19351
19614
  return [];
19352
19615
  const userDir = env[COORDINATOR_CODEX_USER_SKILLS_DIR_ENV]?.trim();
19353
19616
  return [
19354
- ...userDir && isAbsolute7(userDir) ? [userDir] : [],
19355
- ...cwd && isAbsolute7(cwd) ? [join16(cwd, ".claude", "skills")] : []
19617
+ ...userDir && isAbsolute8(userDir) ? [userDir] : [],
19618
+ ...cwd && isAbsolute8(cwd) ? [join17(cwd, ".claude", "skills")] : []
19356
19619
  ].filter((dir) => existsSync3(dir));
19357
19620
  }
19358
19621
  var MAX_SKILL_READ_GRANTS = 256;
19359
19622
  function isWithin(parent, child) {
19360
- const path = relative2(parent, child);
19361
- return path === "" || !path.startsWith(`..${sep}`) && path !== ".." && !isAbsolute7(path);
19623
+ const path = relative3(parent, child);
19624
+ return path === "" || !path.startsWith(`..${sep}`) && path !== ".." && !isAbsolute8(path);
19362
19625
  }
19363
19626
  function codexCoordinatorSkillReadRoots(env = process.env, home = env.HOME?.trim() || homedir2()) {
19364
19627
  const userDir = env[COORDINATOR_CODEX_USER_SKILLS_DIR_ENV]?.trim();
19365
19628
  const roots = [
19366
- ...userDir && isAbsolute7(userDir) ? [userDir] : [],
19367
- join16(home, ".agents", "skills")
19629
+ ...userDir && isAbsolute8(userDir) ? [userDir] : [],
19630
+ join17(home, ".agents", "skills")
19368
19631
  ];
19369
19632
  const homeReal = (() => {
19370
19633
  try {
@@ -19398,8 +19661,8 @@ function codexCoordinatorSkillReadRoots(env = process.env, home = env.HOME?.trim
19398
19661
  break;
19399
19662
  let target;
19400
19663
  try {
19401
- target = realpathSync(join16(real, entry));
19402
- if (!statSync2(target).isDirectory() || !existsSync3(join16(target, "SKILL.md")))
19664
+ target = realpathSync(join17(real, entry));
19665
+ if (!statSync2(target).isDirectory() || !existsSync3(join17(target, "SKILL.md")))
19403
19666
  continue;
19404
19667
  } catch {
19405
19668
  continue;
@@ -19424,7 +19687,7 @@ function codexProjectSkillsConfig(listed) {
19424
19687
  const { path, scope, enabled } = skill ?? {};
19425
19688
  if (enabled === true && typeof scope === "string" && KEPT_SKILL_SCOPES.has(scope))
19426
19689
  continue;
19427
- if (typeof path !== "string" || !isAbsolute7(path)) {
19690
+ if (typeof path !== "string" || !isAbsolute8(path)) {
19428
19691
  throw new Error("Codex listed a project skill without a path it can be disabled by");
19429
19692
  }
19430
19693
  disabled.add(path);
@@ -19543,7 +19806,8 @@ function codexAppServerConfigOverrides(env = process.env) {
19543
19806
  const overrides = {
19544
19807
  "agents.max_concurrent_threads_per_session": String(childLimit),
19545
19808
  "features.multi_agent_v2.max_concurrent_threads_per_session": String(childLimit + 1),
19546
- "features.incremental_tools": "false"
19809
+ "features.incremental_tools": "false",
19810
+ "features.goals": "false"
19547
19811
  };
19548
19812
  const rawUrl = env[ORKESTRATOR_AGENT_MCP_URL_ENV]?.trim();
19549
19813
  const token = env[ORKESTRATOR_AGENT_MCP_TOKEN_ENV]?.trim();
@@ -19552,11 +19816,11 @@ function codexAppServerConfigOverrides(env = process.env) {
19552
19816
  const readableRuntimeRoot = env.CODEX_BRIDGE_READABLE_RUNTIME_ROOT?.trim();
19553
19817
  const projectRoot = env.CWD?.trim();
19554
19818
  const attachmentRoot = env[BRIDGE_ATTACHMENT_ROOT_ENV]?.trim();
19555
- if (!permissionProfile || !/^[A-Za-z0-9_-]+$/.test(permissionProfile) || !readableRuntimeRoot || !isAbsolute7(readableRuntimeRoot) || !projectRoot || !isAbsolute7(projectRoot)) {
19819
+ if (!permissionProfile || !/^[A-Za-z0-9_-]+$/.test(permissionProfile) || !readableRuntimeRoot || !isAbsolute8(readableRuntimeRoot) || !projectRoot || !isAbsolute8(projectRoot)) {
19556
19820
  throw new Error("Coordinator Codex permission profile configuration is invalid");
19557
19821
  }
19558
19822
  overrides.default_permissions = JSON.stringify(permissionProfile);
19559
- overrides[`permissions.${permissionProfile}.filesystem`] = `{ ":root" = "deny", ":minimal" = "read", ":tmpdir" = "deny", ` + `":slash_tmp" = "deny", ${JSON.stringify(readableRuntimeRoot)} = "read", ` + (attachmentRoot && isAbsolute7(attachmentRoot) ? `${JSON.stringify(attachmentRoot)} = "read", ` : "") + codexCoordinatorSkillReadRoots(env).map((root) => `${JSON.stringify(root)} = "read", `).join("") + `":workspace_roots" = { "." = "read" } }`;
19823
+ overrides[`permissions.${permissionProfile}.filesystem`] = `{ ":root" = "deny", ":minimal" = "read", ":tmpdir" = "deny", ` + `":slash_tmp" = "deny", ${JSON.stringify(readableRuntimeRoot)} = "read", ` + (attachmentRoot && isAbsolute8(attachmentRoot) ? `${JSON.stringify(attachmentRoot)} = "read", ` : "") + codexCoordinatorSkillReadRoots(env).map((root) => `${JSON.stringify(root)} = "read", `).join("") + `":workspace_roots" = { "." = "read" } }`;
19560
19824
  overrides[`permissions.${permissionProfile}.network.enabled`] = "false";
19561
19825
  overrides.web_search = JSON.stringify(codexNetworkDeniedSearchMode(codexCoordinatorPolicy(env)));
19562
19826
  overrides["features.standalone_web_search"] = "false";
@@ -19613,7 +19877,12 @@ function codexAppServerConfigOverrides(env = process.env) {
19613
19877
  if (isCoordinatorReadOnlyEnvironment(env)) {
19614
19878
  overrides["mcp_servers.orkestrator.default_tools_approval_mode"] = JSON.stringify("approve");
19615
19879
  } else {
19616
- for (const name of [...AGENT_MAIL_TOOL_NAMES, ...ARTIFACT_TOOL_NAMES]) {
19880
+ for (const name of [
19881
+ ...AGENT_MAIL_TOOL_NAMES,
19882
+ ...ARTIFACT_TOOL_NAMES,
19883
+ ...AGENT_GOAL_TOOL_NAMES,
19884
+ ...KEY_INFORMATION_TOOL_NAMES
19885
+ ]) {
19617
19886
  overrides[`mcp_servers.orkestrator.tools.${name}.approval_mode`] = JSON.stringify("approve");
19618
19887
  }
19619
19888
  }
@@ -19626,7 +19895,7 @@ function codexAppServerConfigOverrides(env = process.env) {
19626
19895
  // ../../bridges/codex-bridge/src/github-credential-config.ts
19627
19896
  import { mkdtemp as mkdtemp2 } from "node:fs/promises";
19628
19897
  import { tmpdir as tmpdir2 } from "node:os";
19629
- import { join as join17 } from "node:path";
19898
+ import { join as join18 } from "node:path";
19630
19899
  var CODEX_INHERITED_GIT_CONFIG_PATTERNS = Object.freeze([
19631
19900
  "GIT_CONFIG_COUNT",
19632
19901
  "GIT_CONFIG_KEY_*",
@@ -19661,7 +19930,7 @@ function codexGitHubCredentialThreadConfig(policy, options) {
19661
19930
  }
19662
19931
  var withheldGhConfigDir;
19663
19932
  function emptyGhConfigDir() {
19664
- withheldGhConfigDir ??= mkdtemp2(join17(tmpdir2(), "orkestrator-gh-withheld-")).catch((error) => {
19933
+ withheldGhConfigDir ??= mkdtemp2(join18(tmpdir2(), "orkestrator-gh-withheld-")).catch((error) => {
19665
19934
  withheldGhConfigDir = undefined;
19666
19935
  throw error;
19667
19936
  });
@@ -19669,11 +19938,11 @@ function emptyGhConfigDir() {
19669
19938
  }
19670
19939
 
19671
19940
  // ../../bridges/codex-bridge/src/sessions/tool-history-guard.ts
19672
- import { open as open6 } from "node:fs/promises";
19941
+ import { open as open7 } from "node:fs/promises";
19673
19942
  var TOOL_HISTORY_MARKER = '"type":"additional_tools"';
19674
19943
  var MAX_TOOL_HISTORY_LINEAGE_DEPTH = 32;
19675
19944
  async function rolloutDeclaresToolHistory(path, end) {
19676
- const handle = await open6(path, "r");
19945
+ const handle = await open7(path, "r");
19677
19946
  try {
19678
19947
  const size = (await handle.stat()).size;
19679
19948
  const limit = end === undefined ? size : Math.min(end, size);
@@ -19698,7 +19967,7 @@ async function rolloutDeclaresToolHistory(path, end) {
19698
19967
  }
19699
19968
  }
19700
19969
  async function historyBase(path) {
19701
- const handle = await open6(path, "r");
19970
+ const handle = await open7(path, "r");
19702
19971
  try {
19703
19972
  const chunks = [];
19704
19973
  let filled = 0;
@@ -19781,10 +20050,12 @@ var APP_SERVER_CAPABILITIES = {
19781
20050
  };
19782
20051
 
19783
20052
  // ../../bridges/codex-bridge/src/engine/app-server-engine.ts
19784
- var AGENT_MAIL_TOOL_APPROVALS = Object.fromEntries([...AGENT_MAIL_TOOL_NAMES, ...ARTIFACT_TOOL_NAMES].map((name) => [
19785
- name,
19786
- { approval_mode: "approve" }
19787
- ]));
20053
+ var AGENT_MAIL_TOOL_APPROVALS = Object.fromEntries([
20054
+ ...AGENT_MAIL_TOOL_NAMES,
20055
+ ...ARTIFACT_TOOL_NAMES,
20056
+ ...AGENT_GOAL_TOOL_NAMES,
20057
+ ...KEY_INFORMATION_TOOL_NAMES
20058
+ ].map((name) => [name, { approval_mode: "approve" }]));
19788
20059
  var ROOT_THREAD_SOURCE_KINDS = ["cli", "vscode", "exec", "appServer", "unknown"];
19789
20060
  var CODEX_SIGN_IN_EXPIRED_NOTICE = "Codex sign-in expired. Sign in again to continue.";
19790
20061
  var CODEX_SIGN_IN_REQUIRED_MESSAGE = "You've been signed out of Codex. Sign in again to keep working.";
@@ -20135,7 +20406,7 @@ function signedOutAccountRead(error) {
20135
20406
  }
20136
20407
  async function readStoredLoginFingerprint(codexHome) {
20137
20408
  try {
20138
- const file = await open7(join18(codexHome, "auth.json"), "r");
20409
+ const file = await open8(join19(codexHome, "auth.json"), "r");
20139
20410
  let raw;
20140
20411
  try {
20141
20412
  const bytes = Buffer.alloc(65537);
@@ -20709,7 +20980,26 @@ class AppServerEngine {
20709
20980
  ]);
20710
20981
  return { ...skills, ...mcp, ...credential };
20711
20982
  }
20712
- toThreadParams(config, extraConfig = {}) {
20983
+ async developerInstructions(generation, config) {
20984
+ const loadsProject = !config.policy || config.policy.projectResources;
20985
+ const cwd = config.cwd ?? this.options.cwd;
20986
+ const ours = [
20987
+ ...config.policy?.id === "coordinator-read-only" ? [] : [agentSystemInstructions()],
20988
+ ...loadsProject || config.sandbox === "read-only" || config.policy?.id === "coordinator-read-only" ? [] : [await readRepositoryInstructions(cwd)]
20989
+ ].filter((part) => Boolean(part));
20990
+ if (ours.length === 0)
20991
+ return;
20992
+ const read = this.options.readConfiguredDeveloperInstructions ?? ((projectCwd) => this.supervisor.requestOnGeneration(generation, "config/read", projectCwd ? { cwd: projectCwd } : {}).then((result) => result?.config?.developer_instructions));
20993
+ const configured = await read(loadsProject ? cwd : undefined).catch(() => {
20994
+ return;
20995
+ });
20996
+ if (typeof configured === "string" && configured.trim())
20997
+ ours.push(configured);
20998
+ return ours.join(`
20999
+
21000
+ `);
21001
+ }
21002
+ toThreadParams(config, extraConfig = {}, developerInstructions) {
20713
21003
  const approveAgentMcpTools = config.policy?.approvals === "auto-approve" && (config.approvalPolicy ?? "never") === "never" && config.sandbox !== "read-only" || config.policy?.id === "coordinator-read-only" && Boolean(config.permissionProfile) || Boolean(config.workflowResultTool && config.agentMcp);
20714
21004
  const cwd = config.cwd ?? this.options.cwd;
20715
21005
  const threadConfig = {
@@ -20753,6 +21043,7 @@ class AppServerEngine {
20753
21043
  },
20754
21044
  ...config.model ? { model: config.model } : {},
20755
21045
  serviceTier: config.serviceTier ?? null,
21046
+ ...developerInstructions ? { developerInstructions } : {},
20756
21047
  ...Object.keys(threadConfig).length > 0 ? { config: threadConfig } : {}
20757
21048
  };
20758
21049
  }
@@ -20815,7 +21106,8 @@ class AppServerEngine {
20815
21106
  const generation = await this.assertHostedNetworkLock(options.config);
20816
21107
  await this.assertToolHistoryLock(generation, options.config);
20817
21108
  const extra = await this.policyThreadConfig(generation, options.config);
20818
- const response = await this.supervisor.requestOnGeneration(generation, "thread/start", this.toThreadParams(options.config, extra));
21109
+ const instructions = await this.developerInstructions(generation, options.config);
21110
+ const response = await this.supervisor.requestOnGeneration(generation, "thread/start", this.toThreadParams(options.config, extra, instructions));
20819
21111
  this.assertPermissionProfile(response.activePermissionProfile, options.config);
20820
21112
  return this.bindThread(response.thread, options.config, response.model);
20821
21113
  }
@@ -20823,7 +21115,11 @@ class AppServerEngine {
20823
21115
  const generation = await this.assertHostedNetworkLock(options.config);
20824
21116
  await this.assertToolHistoryLock(generation, options.config);
20825
21117
  const extra = await this.policyThreadConfig(generation, options.config);
20826
- const response = await this.supervisor.requestOnGeneration(generation, "thread/resume", { threadId, ...this.toThreadParams(options.config, extra) });
21118
+ const instructions = await this.developerInstructions(generation, options.config);
21119
+ const response = await this.supervisor.requestOnGeneration(generation, "thread/resume", {
21120
+ threadId,
21121
+ ...this.toThreadParams(options.config, extra, instructions)
21122
+ });
20827
21123
  this.assertPermissionProfile(response.activePermissionProfile, options.config);
20828
21124
  const thread = this.bindThread(response.thread, options.config, response.model);
20829
21125
  await this.assertNoToolHistory(thread.id ?? threadId, options.config, true);
@@ -20845,10 +21141,11 @@ class AppServerEngine {
20845
21141
  await this.assertToolHistoryLock(generation, config);
20846
21142
  await this.assertNoToolHistory(threadId, config, false);
20847
21143
  const extra = await this.policyThreadConfig(generation, config);
21144
+ const instructions = await this.developerInstructions(generation, config);
20848
21145
  const response = await this.supervisor.requestOnGeneration(generation, "thread/fork", {
20849
21146
  threadId,
20850
21147
  ...lastTurnId ? { lastTurnId } : {},
20851
- ...this.toThreadParams(config, extra)
21148
+ ...this.toThreadParams(config, extra, instructions)
20852
21149
  });
20853
21150
  this.assertPermissionProfile(response.activePermissionProfile, config);
20854
21151
  return this.bindThread(response.thread, config, response.model);
@@ -21178,7 +21475,7 @@ class AppServerEngine {
21178
21475
  thread.model = confirmedModel.trim();
21179
21476
  }
21180
21477
  if (thread.id) {
21181
- if (typeof raw.path === "string" && isAbsolute8(raw.path)) {
21478
+ if (typeof raw.path === "string" && isAbsolute9(raw.path)) {
21182
21479
  this.rolloutPaths.set(thread.id, raw.path);
21183
21480
  }
21184
21481
  this.bindings.set(thread.id, {
@@ -21226,7 +21523,11 @@ class AppServerEngine {
21226
21523
  return {
21227
21524
  id: String(turn.id ?? ""),
21228
21525
  status: turn.status ?? "completed",
21229
- items: [],
21526
+ items: items.flatMap((item) => {
21527
+ const adapted = adaptAppServerItem(item).item;
21528
+ return adapted ? [adapted] : [];
21529
+ }),
21530
+ ...turn.error ? { error: toTurnError(turn.error) } : {},
21230
21531
  clientId: clientIds[0] ?? null,
21231
21532
  clientIds,
21232
21533
  reconciliationItems,
@@ -21377,7 +21678,13 @@ class AppServerEngine {
21377
21678
  clientId
21378
21679
  }))
21379
21680
  }));
21380
- return reconcileFromThreadTurns(turns, requestId);
21681
+ const outcome = reconcileFromThreadTurns(turns, requestId);
21682
+ const matched = thread?.turns?.find((turn) => turn.id === outcome.turnId);
21683
+ return {
21684
+ ...outcome,
21685
+ ...matched?.items.length ? { items: matched.items } : {},
21686
+ ...matched?.error ? { error: matched.error } : {}
21687
+ };
21381
21688
  }
21382
21689
  classifyFailure(error) {
21383
21690
  return {
@@ -22725,8 +23032,10 @@ class CodexRuntimeSessions {
22725
23032
  const session = this.ctx.registry.getSession(sessionId);
22726
23033
  if (!session)
22727
23034
  return { activity: "missing" };
23035
+ const turnFailed = activity === "idle" && (this.ctx.registry.getThreadForSession(sessionId)?.phase ?? (session.restartFailure ? "failed" : "idle")) === "failed";
22728
23036
  return {
22729
23037
  activity,
23038
+ ...turnFailed ? { turnFailed: true } : {},
22730
23039
  ...session.asyncQuestionItemIds.length > 0 ? { asyncQuestionItemIds: [...session.asyncQuestionItemIds] } : {},
22731
23040
  contentRevision: `${ACTIVITY_PROCESS}:${session.contentEpoch}.${session.messageRevision}:${session.asyncQuestionItemIds.length}`
22732
23041
  };
@@ -22771,9 +23080,11 @@ class CodexRuntimeSessions {
22771
23080
  const context = this.ctx.registry.getThreadForSession(sessionId);
22772
23081
  const turn = context?.activeTurn;
22773
23082
  if (context && turn && context.bridgeSessionIds.size === 1) {
22774
- await this.ctx.options.engine.interruptTurn(context.engineHandle, turn.turnId).catch(() => {
22775
- return;
22776
- });
23083
+ if (!await this.lifecycle.capacityRetry.cancelForClose(context, turn)) {
23084
+ await this.ctx.options.engine.interruptTurn(context.engineHandle, turn.turnId).catch(() => {
23085
+ return;
23086
+ });
23087
+ }
22777
23088
  }
22778
23089
  this.retiredSessions.add(session);
22779
23090
  try {
@@ -23092,8 +23403,8 @@ function parseCommandToken(text, sigils = ["/"]) {
23092
23403
 
23093
23404
  // ../../bridges/codex-bridge/src/prompts/template-discovery.ts
23094
23405
  import { createHash as createHash13 } from "node:crypto";
23095
- import { open as open8, readdir as readdir3, stat as stat7 } from "node:fs/promises";
23096
- import { join as join19 } from "node:path";
23406
+ import { open as open9, readdir as readdir3, stat as stat7 } from "node:fs/promises";
23407
+ import { join as join20 } from "node:path";
23097
23408
  var TEMPLATE_LIMITS = Object.freeze({
23098
23409
  maxTemplates: 512,
23099
23410
  maxVisitedEntries: 2048,
@@ -23113,8 +23424,8 @@ var RESERVED_TEMPLATE_PREFIXES = ["/skill:", "/prompts:"];
23113
23424
  var TEMPLATE_ID_PREFIX = "codex-template:";
23114
23425
  function templateRoots(cwd, codexHome = getCodexHomeDir()) {
23115
23426
  return [
23116
- { origin: "project", dir: join19(cwd, ".codex", "prompts") },
23117
- { origin: "user", dir: join19(codexHome, "prompts") }
23427
+ { origin: "project", dir: join20(cwd, ".codex", "prompts") },
23428
+ { origin: "user", dir: join20(codexHome, "prompts") }
23118
23429
  ];
23119
23430
  }
23120
23431
  function templateCommandId(origin, relativePath) {
@@ -23139,7 +23450,7 @@ function isReservedName(name) {
23139
23450
  var metadataCache = new Map;
23140
23451
  var METADATA_CACHE_MAX = 1024;
23141
23452
  async function readBounded2(absolutePath, maxBytes) {
23142
- const handle = await open8(absolutePath, "r");
23453
+ const handle = await open9(absolutePath, "r");
23143
23454
  try {
23144
23455
  const info = await handle.stat();
23145
23456
  if (!info.isFile())
@@ -23219,7 +23530,7 @@ async function scanPromptTemplates(roots, limits = TEMPLATE_LIMITS) {
23219
23530
  return;
23220
23531
  }
23221
23532
  visited += 1;
23222
- const absolutePath = join19(dir, entry.name);
23533
+ const absolutePath = join20(dir, entry.name);
23223
23534
  const relativePath = relative ? `${relative}/${entry.name}` : entry.name;
23224
23535
  if (entry.isDirectory()) {
23225
23536
  if (depth + 1 > limits.maxDepth) {
@@ -23386,7 +23697,7 @@ async function loadTemplateBody(entry, limits = TEMPLATE_LIMITS) {
23386
23697
  }
23387
23698
 
23388
23699
  // ../../bridges/codex-bridge/src/commands/skill-inventory.ts
23389
- import { isAbsolute as isAbsolute9 } from "node:path";
23700
+ import { isAbsolute as isAbsolute10 } from "node:path";
23390
23701
  var SKILL_INVENTORY_LIMITS = Object.freeze({
23391
23702
  maxSkills: 512,
23392
23703
  maxDescriptionBytes: 1000,
@@ -23438,7 +23749,7 @@ function normalizeSkillsList(raw, context) {
23438
23749
  }
23439
23750
  const name = nonEmpty(candidate.name);
23440
23751
  const path = typeof candidate.path === "string" ? candidate.path : undefined;
23441
- if (!name || !usableSkillName(name) || !path || !isAbsolute9(path)) {
23752
+ if (!name || !usableSkillName(name) || !path || !isAbsolute10(path)) {
23442
23753
  truncated = true;
23443
23754
  continue;
23444
23755
  }
@@ -24371,6 +24682,256 @@ class UpdateCoalescer {
24371
24682
  }
24372
24683
  }
24373
24684
 
24685
+ // ../../bridges/codex-bridge/src/app-server-runtime-capacity-retry.ts
24686
+ import { stat as stat8 } from "node:fs/promises";
24687
+ class CodexCapacityRetry {
24688
+ ctx;
24689
+ lifecycle;
24690
+ pending = new Map;
24691
+ constructor(ctx, lifecycle) {
24692
+ this.ctx = ctx;
24693
+ this.lifecycle = lifecycle;
24694
+ }
24695
+ policy() {
24696
+ return { ...DEFAULT_CAPACITY_RETRY_POLICY, ...this.ctx.options.capacityRetry };
24697
+ }
24698
+ isPending(turn) {
24699
+ return this.pending.has(turn);
24700
+ }
24701
+ onTurnFailed(context, turn, error) {
24702
+ const plan = turn.capacityRetry;
24703
+ if (!plan || !turn.requestId || !isModelCapacityError(error))
24704
+ return { retrying: false };
24705
+ const policy = this.policy();
24706
+ if (plan.attempt >= policy.maxAttempts) {
24707
+ return {
24708
+ retrying: false,
24709
+ ...plan.attempt > 1 ? { error: capacityRetriesExhaustedError(error, plan.attempt) } : {}
24710
+ };
24711
+ }
24712
+ if (this.ctx.stopping || turn.cancelRequested || turn.stoppedByShutdown || context.phase !== "running" || context.bridgeSessionIds.size === 0) {
24713
+ return { retrying: false };
24714
+ }
24715
+ const attempt = plan.attempt + 1;
24716
+ const delayMs = capacityRetryDelayMs(policy, attempt, this.ctx.options.capacityRetryRandom);
24717
+ const itemId = capacityRetryItemId(turn.requestId, attempt);
24718
+ turn.settleEndedAttempt();
24719
+ turn.error = undefined;
24720
+ turn.recordRetryCard(itemId, capacityRetryWaitingText(delayMs, attempt, policy.maxAttempts), "pending");
24721
+ const entry = { attempt, itemId, error, stage: "waiting" };
24722
+ entry.timer = setTimeout(() => this.fire(context, turn), delayMs);
24723
+ entry.timer.unref?.();
24724
+ this.pending.set(turn, entry);
24725
+ this.publish(context);
24726
+ return { retrying: true };
24727
+ }
24728
+ stop(context, turn) {
24729
+ const entry = this.pending.get(turn);
24730
+ if (!entry)
24731
+ return false;
24732
+ turn.markCancelling();
24733
+ this.ctx.registry.setPhase(context, "cancelling");
24734
+ this.lifecycle.emitStatus(context);
24735
+ if (entry.stage === "starting") {
24736
+ entry.stopAfterStart = true;
24737
+ return true;
24738
+ }
24739
+ this.end(context, turn, "interrupted");
24740
+ return true;
24741
+ }
24742
+ async cancelForClose(context, turn) {
24743
+ const entry = this.pending.get(turn);
24744
+ if (!entry || !this.stop(context, turn))
24745
+ return false;
24746
+ await entry.work;
24747
+ if (!turn.isTerminal()) {
24748
+ await this.ctx.options.engine.waitForTurnTerminal(context.engineHandle, turn.turnId, {
24749
+ allowRestart: true
24750
+ });
24751
+ if (!turn.isTerminal()) {
24752
+ turn.complete("interrupted");
24753
+ await this.lifecycle.runFinalization(context, turn);
24754
+ }
24755
+ }
24756
+ return true;
24757
+ }
24758
+ endForParentExit(context, turn) {
24759
+ const entry = this.pending.get(turn);
24760
+ if (!entry || entry.stage !== "waiting")
24761
+ return false;
24762
+ turn.stoppedByShutdown = true;
24763
+ this.clear(turn, entry, CAPACITY_RETRY_CANCELLED_TEXT);
24764
+ this.lifecycle.completeRecoveredTurn(turn, "interrupted");
24765
+ this.lifecycle.runFinalization(context, turn);
24766
+ return true;
24767
+ }
24768
+ dispose() {
24769
+ for (const [turn, entry] of Array.from(this.pending)) {
24770
+ if (entry.stage !== "waiting")
24771
+ continue;
24772
+ const context = this.ctx.registry.getThread(turn.threadId);
24773
+ if (!context || context.activeTurn !== turn) {
24774
+ this.clear(turn, entry, CAPACITY_RETRY_CANCELLED_TEXT);
24775
+ continue;
24776
+ }
24777
+ this.end(context, turn, "failed", entry.error, CAPACITY_RETRY_CANCELLED_TEXT);
24778
+ }
24779
+ }
24780
+ discard(turn) {
24781
+ const entry = this.pending.get(turn);
24782
+ if (entry)
24783
+ this.clear(turn, entry, CAPACITY_RETRY_CANCELLED_TEXT);
24784
+ }
24785
+ fire(context, turn) {
24786
+ const entry = this.pending.get(turn);
24787
+ if (!entry || entry.stage !== "waiting")
24788
+ return;
24789
+ entry.timer = undefined;
24790
+ if (!this.owns(context, turn)) {
24791
+ if (context.activeTurn === turn && !turn.isTerminal()) {
24792
+ this.end(context, turn, "failed", entry.error, CAPACITY_RETRY_CANCELLED_TEXT);
24793
+ } else
24794
+ this.clear(turn, entry, CAPACITY_RETRY_CANCELLED_TEXT);
24795
+ return;
24796
+ }
24797
+ entry.stage = "starting";
24798
+ const work = this.startContinuation(context, turn, entry).catch((error) => {
24799
+ console.error(`[codex-bridge] Capacity retry of turn ${turn.turnId} failed:`, error instanceof Error ? error.message : error);
24800
+ if (this.pending.get(turn) === entry && context.activeTurn === turn && !turn.isTerminal()) {
24801
+ this.end(context, turn, "failed", entry.error, CAPACITY_RETRY_START_FAILED_TEXT);
24802
+ }
24803
+ });
24804
+ entry.work = work;
24805
+ this.ctx.pendingFinalizations.add(work);
24806
+ work.finally(() => this.ctx.pendingFinalizations.delete(work));
24807
+ }
24808
+ owns(context, turn) {
24809
+ return !this.ctx.stopping && this.ctx.registry.getThread(context.threadId) === context && context.activeTurn === turn && !turn.isTerminal() && !turn.cancelRequested && context.phase === "running" && context.bridgeSessionIds.size > 0 && turn.engineGeneration === this.ctx.options.engine.info().generation;
24810
+ }
24811
+ async startContinuation(context, turn, entry) {
24812
+ const plan = turn.capacityRetry;
24813
+ const requestId = turn.requestId;
24814
+ const policy = this.policy();
24815
+ const clientId = capacityRetryClientId(requestId, entry.attempt);
24816
+ const engine = this.ctx.options.engine;
24817
+ const previousTurnId = turn.turnId;
24818
+ turn.providerRequestId = clientId;
24819
+ turn.turnId = unconfirmedTurnId(clientId);
24820
+ await this.ctx.journal.markContinuation(requestId, clientId);
24821
+ plan.attempt = entry.attempt;
24822
+ const path = engine.rolloutPath(context.threadId);
24823
+ const offset = path ? await stat8(path).then((stats) => stats.size, () => {
24824
+ return;
24825
+ }) : undefined;
24826
+ this.lifecycle.stateFor(context.threadId).refusedCellOffset = offset;
24827
+ let started;
24828
+ let reconciled;
24829
+ try {
24830
+ started = await engine.startTurn({
24831
+ handle: context.engineHandle,
24832
+ input: [
24833
+ { type: "text", text: capacityRetryContinuationText(entry.attempt, policy.maxAttempts) }
24834
+ ],
24835
+ config: plan.config,
24836
+ requestId: clientId,
24837
+ outputSchema: plan.outputSchema
24838
+ });
24839
+ } catch (error) {
24840
+ const failure = engine.classifyFailure(error);
24841
+ if (!this.ctx.stopping && failure.class !== "rejected" && !failure.retryImmediately) {
24842
+ const outcome = await engine.reconcileRequest(context.threadId, clientId).catch(() => {
24843
+ return;
24844
+ });
24845
+ if (outcome && outcome.result !== "absent" && outcome.turnId) {
24846
+ started = { turnId: outcome.turnId, engineGeneration: engine.info().generation };
24847
+ reconciled = outcome;
24848
+ } else if (!outcome) {
24849
+ this.clear(turn, entry, CAPACITY_RETRY_START_FAILED_TEXT);
24850
+ this.ctx.registry.setPhase(context, "recovering");
24851
+ this.lifecycle.emitStatus(context);
24852
+ this.ctx.callbacks.scheduleRecoveryBackstop(context);
24853
+ return;
24854
+ }
24855
+ }
24856
+ if (!started) {
24857
+ turn.turnId = previousTurnId;
24858
+ this.end(context, turn, entry.stopAfterStart ? "interrupted" : "failed", entry.error, CAPACITY_RETRY_START_FAILED_TEXT);
24859
+ return;
24860
+ }
24861
+ }
24862
+ if (this.pending.get(turn) !== entry || context.activeTurn !== turn || turn.isTerminal()) {
24863
+ await engine.interruptTurn(context.engineHandle, started.turnId).catch(() => {
24864
+ return;
24865
+ });
24866
+ return;
24867
+ }
24868
+ await this.ctx.journal.markAccepted(requestId, { threadId: context.threadId, turnId: started.turnId }).catch((error) => console.warn(`[codex-bridge] Could not journal capacity retry of ${requestId}:`, error instanceof Error ? error.message : error));
24869
+ if (plan.outputSchema) {
24870
+ const ledger = this.ctx.registry.recordStructuredOutputTurn(context.threadId, started.turnId, false);
24871
+ await Promise.all(ledger.map((session) => this.ctx.callbacks.persistSession(session)));
24872
+ }
24873
+ turn.turnId = started.turnId;
24874
+ turn.engineGeneration = started.engineGeneration;
24875
+ context.engineGeneration = started.engineGeneration;
24876
+ if (entry.stopAfterStart)
24877
+ this.clear(turn, entry, CAPACITY_RETRY_CANCELLED_TEXT);
24878
+ else {
24879
+ this.clear(turn, entry, capacityRetryStartedText(entry.attempt, policy.maxAttempts), "success");
24880
+ }
24881
+ if (reconciled?.items) {
24882
+ for (const item of reconciled.items)
24883
+ turn.onItemCompleted(item);
24884
+ }
24885
+ this.publish(context);
24886
+ this.lifecycle.drainPendingEvents(context, started.turnId);
24887
+ if (reconciled?.result === "terminal" && context.activeTurn === turn && !turn.isTerminal() && !this.isPending(turn)) {
24888
+ this.lifecycle.applyEvent(context, {
24889
+ kind: "turn.completed",
24890
+ threadId: context.threadId,
24891
+ turnId: started.turnId,
24892
+ engineGeneration: started.engineGeneration,
24893
+ status: reconciled.status ?? "completed",
24894
+ error: reconciled.error
24895
+ });
24896
+ }
24897
+ if (entry.stopAfterStart && !turn.isTerminal()) {
24898
+ const sessionId = context.bridgeSessionIds.values().next().value;
24899
+ if (sessionId)
24900
+ await this.ctx.callbacks.abort(sessionId);
24901
+ else
24902
+ await engine.interruptTurn(context.engineHandle, started.turnId).catch(() => {
24903
+ return;
24904
+ });
24905
+ }
24906
+ }
24907
+ end(context, turn, status, error, cardText = CAPACITY_RETRY_CANCELLED_TEXT) {
24908
+ const entry = this.pending.get(turn);
24909
+ if (entry)
24910
+ this.clear(turn, entry, cardText);
24911
+ if (status === "failed" && error) {
24912
+ turn.complete("failed", error);
24913
+ turn.recordProviderFailure(error);
24914
+ } else
24915
+ turn.complete(status);
24916
+ const work = this.lifecycle.runFinalization(context, turn);
24917
+ if (entry)
24918
+ entry.work = work;
24919
+ }
24920
+ clear(turn, entry, cardText, state = "failure") {
24921
+ if (entry.timer)
24922
+ clearTimeout(entry.timer);
24923
+ entry.timer = undefined;
24924
+ this.pending.delete(turn);
24925
+ if (turn.retryCardState(entry.itemId) === "pending") {
24926
+ turn.recordRetryCard(entry.itemId, cardText, state);
24927
+ }
24928
+ }
24929
+ publish(context) {
24930
+ this.lifecycle.stateFor(context.threadId).coalescer.flushNow();
24931
+ this.lifecycle.emitStatus(context);
24932
+ }
24933
+ }
24934
+
24374
24935
  // ../../bridges/codex-bridge/src/app-server-runtime-lifecycle.ts
24375
24936
  function artifactConnectionToken(value) {
24376
24937
  if (!value || typeof value !== "object" || Array.isArray(value))
@@ -24381,8 +24942,10 @@ function artifactConnectionToken(value) {
24381
24942
 
24382
24943
  class CodexRuntimeLifecycle {
24383
24944
  ctx;
24945
+ capacityRetry;
24384
24946
  constructor(ctx) {
24385
24947
  this.ctx = ctx;
24948
+ this.capacityRetry = new CodexCapacityRetry(ctx, this);
24386
24949
  }
24387
24950
  async start() {
24388
24951
  if (this.ctx.started)
@@ -24464,6 +25027,7 @@ class CodexRuntimeLifecycle {
24464
25027
  clearTimeout(timer);
24465
25028
  this.ctx.recoveryBackstops.clear();
24466
25029
  this.ctx.commandCatalogue.dispose();
25030
+ this.capacityRetry.dispose();
24467
25031
  this.ctx.callbacks.notifyThreadActivity();
24468
25032
  await this.ctx.options.engine.stop();
24469
25033
  await this.drainPendingWork();
@@ -25144,12 +25708,23 @@ class CodexRuntimeLifecycle {
25144
25708
  this.setThreadAuthNotice(context, refusedLoginNotice(context.authNotice, this.ctx.options.engine.getAccountLoginKind(), () => crypto.randomUUID()));
25145
25709
  }
25146
25710
  this.discardOutlivingCommandWindows(turn);
25711
+ let failure = event.error;
25712
+ if (event.status === "failed") {
25713
+ const decision = this.capacityRetry.onTurnFailed(context, turn, event.error);
25714
+ if (decision.retrying) {
25715
+ this.ctx.options.changeEvidence?.turn(this.evidenceSource(context, turn), "failed");
25716
+ this.takeRefusedCellTail(threadId, turn)?.close();
25717
+ return;
25718
+ }
25719
+ if (decision.error)
25720
+ failure = decision.error;
25721
+ }
25147
25722
  if (turn.stoppedByShutdown && event.status === "interrupted")
25148
25723
  this.completeRecoveredTurn(turn, event.status);
25149
25724
  else {
25150
- turn.complete(event.status, event.error);
25151
- if (event.status === "failed" && event.error)
25152
- turn.recordProviderFailure(event.error);
25725
+ turn.complete(event.status, failure);
25726
+ if (event.status === "failed" && failure)
25727
+ turn.recordProviderFailure(failure);
25153
25728
  }
25154
25729
  this.ctx.options.changeEvidence?.turn(this.evidenceSource(context, turn), event.status);
25155
25730
  const finalize = () => this.runFinalization(context, turn).catch((error) => {
@@ -25627,8 +26202,14 @@ class CodexRuntimeLifecycle {
25627
26202
  this.emitStatus(context);
25628
26203
  continue;
25629
26204
  }
25630
- const outcome = await this.ctx.options.engine.reconcileRequest(context.threadId, turn.requestId);
26205
+ const outcome = await this.ctx.options.engine.reconcileRequest(context.threadId, turn.providerRequestId ?? turn.requestId);
25631
26206
  if (outcome.result === "terminal") {
26207
+ if (outcome.turnId)
26208
+ turn.turnId = outcome.turnId;
26209
+ for (const item of outcome.items ?? [])
26210
+ turn.onItemCompleted(item);
26211
+ if (outcome.error)
26212
+ turn.onError(outcome.error);
25632
26213
  this.completeRecoveredTurn(turn, outcome.status ?? "completed");
25633
26214
  await this.runFinalization(context, turn);
25634
26215
  continue;
@@ -25678,6 +26259,7 @@ class CodexRuntimeLifecycle {
25678
26259
  turn.complete(status);
25679
26260
  }
25680
26261
  async finalizeTurn(context, turn) {
26262
+ this.capacityRetry.discard(turn);
25681
26263
  const state = this.stateFor(context.threadId);
25682
26264
  const structuredResult = turn.expectsStructuredOutput ? parseCodexStructuredOutput(turn) : undefined;
25683
26265
  const structuredSessions = structuredResult ? [...context.bridgeSessionIds].map((sessionId) => this.ctx.registry.getSession(sessionId)).filter((session) => session?.structuredOutputRequestId === turn.requestId) : [];
@@ -25940,7 +26522,7 @@ function requiredCoordinatorPermissionProfile() {
25940
26522
  }
25941
26523
 
25942
26524
  // ../../bridges/codex-bridge/src/app-server-runtime-prompt.ts
25943
- import { stat as stat8 } from "node:fs/promises";
26525
+ import { stat as stat9 } from "node:fs/promises";
25944
26526
  function commandRefusal(message) {
25945
26527
  return { ok: false, status: 422, error: message, kind: "command-unavailable" };
25946
26528
  }
@@ -26043,7 +26625,7 @@ class CodexRuntimePrompt {
26043
26625
  };
26044
26626
  }
26045
26627
  if (decision.action === "reconcile" && decision.record?.threadId) {
26046
- const outcome = await this.ctx.options.engine.reconcileRequest(decision.record.threadId, requestId);
26628
+ const outcome = await this.ctx.options.engine.reconcileRequest(decision.record.threadId, decision.record.providerRequestId ?? requestId);
26047
26629
  if (outcome.result === "terminal") {
26048
26630
  await this.ctx.journal.markTerminal(requestId, outcome.status ?? "completed", {
26049
26631
  threadId: decision.record.threadId,
@@ -26307,7 +26889,7 @@ class CodexRuntimePrompt {
26307
26889
  let refusedCellOffset;
26308
26890
  const startTurn = async () => {
26309
26891
  const path = this.ctx.options.engine.rolloutPath(context.threadId);
26310
- refusedCellOffset = path ? await stat8(path).then((stats) => stats.size, (error) => error.code === "ENOENT" ? 0 : undefined) : undefined;
26892
+ refusedCellOffset = path ? await stat9(path).then((stats) => stats.size, (error) => error.code === "ENOENT" ? 0 : undefined) : undefined;
26311
26893
  return this.ctx.options.engine.startTurn({
26312
26894
  handle: context.engineHandle,
26313
26895
  input: engineInput,
@@ -26464,6 +27046,11 @@ class CodexRuntimePrompt {
26464
27046
  startedAt: context.turnStartedAt
26465
27047
  });
26466
27048
  accumulator.markRunning();
27049
+ accumulator.capacityRetry = {
27050
+ config: turnConfig,
27051
+ ...input.outputSchema ? { outputSchema: input.outputSchema } : {},
27052
+ attempt: 1
27053
+ };
26467
27054
  context.activeTurn = accumulator;
26468
27055
  context.engineGeneration = turn.engineGeneration;
26469
27056
  context.dispatchInFlight = false;
@@ -26590,10 +27177,11 @@ class CodexRuntimePrompt {
26590
27177
  ...recoveredModelId ? { modelId: recoveredModelId } : {}
26591
27178
  });
26592
27179
  }
27180
+ accumulator.providerRequestId = this.ctx.journal.get(requestId)?.providerRequestId ?? requestId;
26593
27181
  this.scheduleRecoveryBackstop(context);
26594
27182
  let outcome;
26595
27183
  try {
26596
- outcome = await this.ctx.options.engine.reconcileRequest(context.threadId, requestId);
27184
+ outcome = await this.ctx.options.engine.reconcileRequest(context.threadId, accumulator.providerRequestId);
26597
27185
  } catch (error) {
26598
27186
  console.warn(`[codex-bridge] Could not reconcile ${requestId} on thread ${context.threadId}:`, error instanceof Error ? error.message : error);
26599
27187
  return "recovering";
@@ -26899,7 +27487,7 @@ class CodexRuntimePrompt {
26899
27487
  }
26900
27488
 
26901
27489
  // ../../bridges/codex-bridge/src/app-server-runtime-tail.ts
26902
- import { join as join20, relative as relative3, isAbsolute as isAbsolute10 } from "node:path";
27490
+ import { join as join21, relative as relative4, isAbsolute as isAbsolute11 } from "node:path";
26903
27491
  class CodexRuntimeTail {
26904
27492
  ctx;
26905
27493
  lifecycle;
@@ -26915,6 +27503,8 @@ class CodexRuntimeTail {
26915
27503
  const turn = context.activeTurn;
26916
27504
  if (!turn || turn.isTerminal() || turn.isUnconfirmed())
26917
27505
  continue;
27506
+ if (this.lifecycle.capacityRetry.endForParentExit(context, turn))
27507
+ continue;
26918
27508
  turn.stoppedByShutdown = true;
26919
27509
  const { engineHandle } = context;
26920
27510
  stopping.push(this.ctx.options.engine.interruptTurn(engineHandle, turn.turnId).then(() => this.ctx.options.engine.waitForTurnTerminal(engineHandle, turn.turnId, {
@@ -26950,6 +27540,9 @@ class CodexRuntimeTail {
26950
27540
  phase: context?.phase ?? "idle"
26951
27541
  };
26952
27542
  }
27543
+ if (this.lifecycle.capacityRetry.stop(context, turn)) {
27544
+ return { status: "cancelling", phase: "cancelling" };
27545
+ }
26953
27546
  this.ctx.threadState.get(context.threadId)?.refusedCellTail?.tail.close();
26954
27547
  turn.markCancelling();
26955
27548
  this.ctx.registry.setPhase(context, "cancelling");
@@ -27051,9 +27644,10 @@ class CodexRuntimeTail {
27051
27644
  const windows = accountUsageFromLimits(limits);
27052
27645
  return windows.length > 0 ? windows : undefined;
27053
27646
  }
27054
- async listSessions() {
27647
+ async listSessions(options = {}) {
27055
27648
  const cwd = getWorkingDirectory(this.ctx.options.cwd);
27056
27649
  const merged = new Map;
27650
+ const archivedRows = new Map;
27057
27651
  try {
27058
27652
  const { threads } = await this.ctx.options.engine.listThreads({ cwd });
27059
27653
  for (const thread of threads) {
@@ -27078,20 +27672,27 @@ class CodexRuntimeTail {
27078
27672
  onlyArchived: true,
27079
27673
  ...cursor ? { cursor } : {}
27080
27674
  });
27081
- for (const thread of page.threads)
27082
- if (thread.id)
27083
- archived.add(thread.id);
27675
+ for (const thread of page.threads) {
27676
+ if (!thread.id)
27677
+ continue;
27678
+ archived.add(thread.id);
27679
+ archivedRows.set(thread.id, {
27680
+ id: thread.id,
27681
+ title: thread.name ?? thread.preview ?? undefined,
27682
+ updatedAt: thread.updatedAt ?? new Date(this.ctx.now()).toISOString()
27683
+ });
27684
+ }
27084
27685
  cursor = page.nextCursor ?? undefined;
27085
27686
  } while (cursor);
27086
27687
  } catch {}
27087
- const archivedRoot = join20(this.ctx.options.codexHome, "archived_sessions");
27688
+ const archivedRoot = join21(this.ctx.options.codexHome, "archived_sessions");
27088
27689
  const isArchived = (meta) => {
27089
27690
  if (archived.has(meta.id))
27090
27691
  return true;
27091
27692
  if (!meta.transcriptPath)
27092
27693
  return false;
27093
- const fromRoot = relative3(archivedRoot, meta.transcriptPath);
27094
- return fromRoot !== "" && !fromRoot.startsWith("..") && !isAbsolute10(fromRoot);
27694
+ const fromRoot = relative4(archivedRoot, meta.transcriptPath);
27695
+ return fromRoot !== "" && !fromRoot.startsWith("..") && !isAbsolute11(fromRoot);
27095
27696
  };
27096
27697
  let persisted = [];
27097
27698
  let generatedTitles = null;
@@ -27105,6 +27706,9 @@ class CodexRuntimeTail {
27105
27706
  for (const meta of persisted) {
27106
27707
  if (isArchived(meta)) {
27107
27708
  merged.delete(meta.id);
27709
+ if (!archivedRows.has(meta.id)) {
27710
+ archivedRows.set(meta.id, { id: meta.id, title: meta.title, updatedAt: meta.updatedAt });
27711
+ }
27108
27712
  continue;
27109
27713
  }
27110
27714
  const existing = merged.get(meta.id);
@@ -27117,14 +27721,18 @@ class CodexRuntimeTail {
27117
27721
  }
27118
27722
  try {
27119
27723
  const generated = generatedTitles ?? await readPersistedSessionTitleEntries(this.ctx.options.codexHome);
27120
- for (const session of merged.values()) {
27724
+ for (const session of [...merged.values(), ...archivedRows.values()]) {
27121
27725
  const entry = generated.get(session.id);
27122
27726
  if (entry)
27123
27727
  session.title = entry.title;
27124
27728
  }
27125
27729
  } catch {}
27730
+ const byActivity = (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime();
27126
27731
  return {
27127
- sessions: [...merged.values()].sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()),
27732
+ sessions: [
27733
+ ...boundedResumeRows([...merged.values()].sort(byActivity)),
27734
+ ...options.includeArchived ? boundedResumeRows([...archivedRows.values()].filter((row) => !merged.has(row.id)).sort(byActivity).map((row) => ({ ...row, archived: true }))) : []
27735
+ ],
27128
27736
  cwd
27129
27737
  };
27130
27738
  }
@@ -27160,6 +27768,21 @@ class CodexRuntimeTail {
27160
27768
  };
27161
27769
  }
27162
27770
  }
27771
+ function boundedResumeRows(rows) {
27772
+ const result = [];
27773
+ let remaining = 900 * 1024;
27774
+ for (const row of rows) {
27775
+ if (result.length >= 512)
27776
+ break;
27777
+ const bounded = { ...row, title: row.title?.slice(0, 512) };
27778
+ const bytes = Buffer.byteLength(JSON.stringify(bounded), "utf8") + 1;
27779
+ if (bytes > remaining)
27780
+ continue;
27781
+ remaining -= bytes;
27782
+ result.push(bounded);
27783
+ }
27784
+ return result;
27785
+ }
27163
27786
 
27164
27787
  // ../../bridges/codex-bridge/src/app-server-runtime.ts
27165
27788
  class AppServerRuntime {
@@ -27967,7 +28590,7 @@ async function writeCodexRawLog(sessionId, entry, logDir = codexRawLogDir) {
27967
28590
  try {
27968
28591
  await mkdir9(logDir, { recursive: true });
27969
28592
  const filename = `${sanitizeLogFileComponent(sessionId)}.jsonl`;
27970
- await appendFile5(join21(logDir, filename), `${JSON.stringify({
28593
+ await appendFile5(join22(logDir, filename), `${JSON.stringify({
27971
28594
  timestamp: new Date().toISOString(),
27972
28595
  sessionId,
27973
28596
  ...entry
@@ -28159,10 +28782,10 @@ function emit(event) {
28159
28782
  }
28160
28783
  }
28161
28784
  function bridgeCacheDir() {
28162
- return join21(getCodexHomeDir(), "orkestrator-bridge");
28785
+ return join22(getCodexHomeDir(), "orkestrator-bridge");
28163
28786
  }
28164
28787
  function bridgeCachePath() {
28165
- return join21(bridgeCacheDir(), "models-cache.json");
28788
+ return join22(bridgeCacheDir(), "models-cache.json");
28166
28789
  }
28167
28790
  var BRIDGE_MODEL_CACHE_VERSION = 2;
28168
28791
  async function readPersistedBridgeCache() {
@@ -28186,7 +28809,7 @@ async function writePersistedBridgeCache(models) {
28186
28809
  }
28187
28810
  async function readCodexCliModelCache() {
28188
28811
  try {
28189
- const raw = await readFile7(join21(getCodexHomeDir(), "models_cache.json"), "utf8");
28812
+ const raw = await readFile7(join22(getCodexHomeDir(), "models_cache.json"), "utf8");
28190
28813
  const models = parseModelCatalog(raw);
28191
28814
  return models.length > 0 ? models : null;
28192
28815
  } catch {
@@ -28536,7 +29159,9 @@ app.post("/session/:id/commands/refresh", async (c) => {
28536
29159
  return c.json(await appServerRuntime.refreshCommandCatalogue(c.req.param("id")));
28537
29160
  });
28538
29161
  app.get("/session/list", async (c) => {
28539
- return c.json(await appServerRuntime.listSessions());
29162
+ return c.json(await appServerRuntime.listSessions({
29163
+ includeArchived: c.req.query("includeArchived") === "1"
29164
+ }));
28540
29165
  });
28541
29166
  for (const action of ["archive", "unarchive"]) {
28542
29167
  app.post(`/session/list/:threadId/${action}`, async (c) => {