@agentclientprotocol/codex-acp 1.12.0 → 1.12.1-preview.2

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.
Files changed (2) hide show
  1. package/dist/index.js +270 -72
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -22893,11 +22893,17 @@ function stripShellPrefix(command) {
22893
22893
  // src/TerminalOutputMode.ts
22894
22894
  function resolveTerminalOutputMode(clientCapabilities) {
22895
22895
  const meta3 = clientCapabilities?._meta;
22896
+ if (meta3?.["terminal_output_delta"] === true) {
22897
+ return "terminal_output_delta";
22898
+ }
22896
22899
  if (meta3?.["terminal_output"] === true) {
22897
22900
  return "terminal_output";
22898
22901
  }
22899
22902
  return "terminal_output_delta";
22900
22903
  }
22904
+ function clientSupportsTerminalOutputDelta(clientCapabilities) {
22905
+ return clientCapabilities?._meta?.["terminal_output_delta"] === true;
22906
+ }
22901
22907
  function createTerminalOutputMeta(mode, terminalId, data) {
22902
22908
  switch (mode) {
22903
22909
  case "terminal_output":
@@ -23921,19 +23927,24 @@ var CodexSubagentEventRouter = class _CodexSubagentEventRouter {
23921
23927
  closingChildSessions(notification) {
23922
23928
  if (!this.supported) return [];
23923
23929
  if (notification.method === "turn/completed") {
23924
- if (terminalStateFromTurn(notification.params.turn.status) === void 0) return [];
23925
- return this.closingChildSession(notification.params.threadId);
23930
+ const state = terminalStateFromTurn(notification.params.turn.status);
23931
+ if (state === void 0) return [];
23932
+ if (notification.params.threadId === this.rootSessionId && state !== "completed") {
23933
+ return [...this.children.keys()].flatMap((threadId) => this.closingChildSession(threadId, state));
23934
+ }
23935
+ return this.closingChildSession(notification.params.threadId, state);
23926
23936
  }
23927
23937
  if (notification.method !== "item/started" && notification.method !== "item/completed") return [];
23928
23938
  const item = notification.params.item;
23929
23939
  if (item.type === "subAgentActivity") {
23930
- return item.kind === "interrupted" ? this.closingChildSession(item.agentThreadId) : [];
23940
+ return item.kind === "interrupted" ? this.closingChildSession(item.agentThreadId, "cancelled") : [];
23931
23941
  }
23932
23942
  if (item.type !== "collabAgentToolCall") return [];
23933
23943
  const closing = /* @__PURE__ */ new Map();
23934
23944
  for (const [threadId, state] of Object.entries(item.agentsStates)) {
23935
- if (!state || terminalStateOf(state.status) === void 0) continue;
23936
- for (const child of this.closingChildSession(threadId)) closing.set(threadId, child);
23945
+ const terminalState = state && terminalStateOf(state.status);
23946
+ if (!terminalState) continue;
23947
+ for (const child of this.closingChildSession(threadId, terminalState)) closing.set(threadId, child);
23937
23948
  }
23938
23949
  return [...closing.values()];
23939
23950
  }
@@ -23965,15 +23976,15 @@ var CodexSubagentEventRouter = class _CodexSubagentEventRouter {
23965
23976
  const sessionUpdate = this.activeLegacyActivities.delete(item.id) ? "tool_call_update" : "tool_call";
23966
23977
  return createSubAgentActivityUpdate(item, "completed", sessionUpdate);
23967
23978
  }
23979
+ /** The caller finalizes pending child updates before closing timed-out sessions. */
23968
23980
  async wait(signal, timeoutMs = _CodexSubagentEventRouter.DEFAULT_WAIT_TIMEOUT_MS) {
23969
23981
  const deadline = Date.now() + timeoutMs;
23970
23982
  while (this.hasOutstanding()) {
23971
- if (signal.aborted) return;
23983
+ if (signal.aborted) return "aborted";
23972
23984
  const remainingMs = deadline - Date.now();
23973
23985
  if (remainingMs <= 0) {
23974
23986
  logger.log(`Timed out waiting for subagents in session ${this.rootSessionId}; marking them failed`);
23975
- await this.finishOutstanding("failed");
23976
- return;
23987
+ return "timed_out";
23977
23988
  }
23978
23989
  const changed = await new Promise((resolve) => {
23979
23990
  const timeout = setTimeout(() => {
@@ -23996,10 +24007,10 @@ var CodexSubagentEventRouter = class _CodexSubagentEventRouter {
23996
24007
  });
23997
24008
  if (!changed) {
23998
24009
  logger.log(`Timed out waiting for subagents in session ${this.rootSessionId}; marking them failed`);
23999
- await this.finishOutstanding("failed");
24000
- return;
24010
+ return "timed_out";
24001
24011
  }
24002
24012
  }
24013
+ return "settled";
24003
24014
  }
24004
24015
  async finishOutstanding(state) {
24005
24016
  for (const childSessionId of [...this.pendingSpawns.keys()]) {
@@ -24012,9 +24023,9 @@ var CodexSubagentEventRouter = class _CodexSubagentEventRouter {
24012
24023
  isKnownChild(threadId) {
24013
24024
  return threadId !== this.rootSessionId && (this.children.has(threadId) || this.pendingSpawns.has(threadId) || this.terminalPendingSpawns.has(threadId));
24014
24025
  }
24015
- closingChildSession(threadId) {
24026
+ closingChildSession(threadId, state) {
24016
24027
  const child = this.children.get(threadId);
24017
- return child && child.terminalState === void 0 ? [{ threadId, sessionId: child.sessionId }] : [];
24028
+ return child && child.terminalState === void 0 ? [{ threadId, sessionId: child.sessionId, state }] : [];
24018
24029
  }
24019
24030
  async materialize(childSessionId, path9) {
24020
24031
  if (this.children.has(childSessionId)) return;
@@ -24577,6 +24588,25 @@ var STRUCTURED_CODEX_ERROR_CATEGORIES = {
24577
24588
  activeTurnNotSteerable: "provider_error"
24578
24589
  };
24579
24590
  var CodexEventHandler = class _CodexEventHandler {
24591
+ constructor(connection, sessionState, supportsPlanUpdates = false, supportsTypedSessionFailures = false, sessionFailureEpoch = randomUUID(), subagents = new CodexSubagentEventRouter(
24592
+ sessionState.sessionId,
24593
+ false,
24594
+ new ACPSessionConnection(connection, sessionState.sessionId)
24595
+ ), onAccountUpdated, collectTurnDiffs = false, supportsCompaction = false) {
24596
+ this.supportsCompaction = supportsCompaction;
24597
+ this.onAccountUpdated = onAccountUpdated;
24598
+ this.sessionState = sessionState;
24599
+ this.supportsPlanUpdates = supportsPlanUpdates;
24600
+ this.supportsTypedSessionFailures = supportsTypedSessionFailures;
24601
+ this.sessionFailureEpoch = sessionFailureEpoch;
24602
+ this.session = new ACPSessionConnection(connection, sessionState.sessionId);
24603
+ this.subagents = subagents;
24604
+ this.collectTurnDiffs = collectTurnDiffs;
24605
+ if (sessionState.sessionFailure !== void 0) {
24606
+ this.failuresById.set(sessionState.sessionFailure.id, sessionState.sessionFailure);
24607
+ }
24608
+ }
24609
+ supportsCompaction;
24580
24610
  static PLAN_UPDATE_INTERVAL_MS = 150;
24581
24611
  sessionState;
24582
24612
  supportsPlanUpdates;
@@ -24604,7 +24634,7 @@ var CodexEventHandler = class _CodexEventHandler {
24604
24634
  disposed = false;
24605
24635
  seenReasoningDeltaItemIds = /* @__PURE__ */ new Set();
24606
24636
  terminalCommandIds = /* @__PURE__ */ new Set();
24607
- terminalCommandOutputIds = /* @__PURE__ */ new Set();
24637
+ commandOutputIds = /* @__PURE__ */ new Set();
24608
24638
  agentMessagePhases = /* @__PURE__ */ new Map();
24609
24639
  turnDiffs = /* @__PURE__ */ new Map();
24610
24640
  oversizedTurnDiffs = /* @__PURE__ */ new Set();
@@ -24612,23 +24642,6 @@ var CodexEventHandler = class _CodexEventHandler {
24612
24642
  subagents;
24613
24643
  /** Connection-level `authStatus` sink; the app-server account push feeds it. */
24614
24644
  onAccountUpdated;
24615
- constructor(connection, sessionState, supportsPlanUpdates = false, supportsTypedSessionFailures = false, sessionFailureEpoch = randomUUID(), subagents = new CodexSubagentEventRouter(
24616
- sessionState.sessionId,
24617
- false,
24618
- new ACPSessionConnection(connection, sessionState.sessionId)
24619
- ), onAccountUpdated, collectTurnDiffs = false) {
24620
- this.onAccountUpdated = onAccountUpdated;
24621
- this.sessionState = sessionState;
24622
- this.supportsPlanUpdates = supportsPlanUpdates;
24623
- this.supportsTypedSessionFailures = supportsTypedSessionFailures;
24624
- this.sessionFailureEpoch = sessionFailureEpoch;
24625
- this.session = new ACPSessionConnection(connection, sessionState.sessionId);
24626
- this.subagents = subagents;
24627
- this.collectTurnDiffs = collectTurnDiffs;
24628
- if (sessionState.sessionFailure !== void 0) {
24629
- this.failuresById.set(sessionState.sessionFailure.id, sessionState.sessionFailure);
24630
- }
24631
- }
24632
24645
  getFailure() {
24633
24646
  return this.failure;
24634
24647
  }
@@ -24662,6 +24675,7 @@ var CodexEventHandler = class _CodexEventHandler {
24662
24675
  await this.handleNotification(notification);
24663
24676
  return;
24664
24677
  }
24678
+ await this.finishCompactionsForNotification(notification);
24665
24679
  if (notification.params.willRetry) {
24666
24680
  await this.session.update(this.createSessionFailureUpdate(this.recordRetryWarning(notification.params, false)));
24667
24681
  return;
@@ -24733,8 +24747,13 @@ var CodexEventHandler = class _CodexEventHandler {
24733
24747
  }
24734
24748
  async handleNotification(notification) {
24735
24749
  await this.flushPendingErrors();
24750
+ await this.finishCompactionsForNotification(notification);
24736
24751
  const closingChildren = this.subagents.closingChildSessions(notification);
24737
24752
  for (const child of closingChildren) {
24753
+ await this.finishOutstandingCompactions(
24754
+ child.state === "cancelled" ? "cancelled" : "failed",
24755
+ child.sessionId
24756
+ );
24738
24757
  await this.sessionState.asyncTasks.reconcile(child.threadId, child.sessionId);
24739
24758
  }
24740
24759
  const handledBySubagents = await this.subagents.handle(notification);
@@ -24764,11 +24783,45 @@ var CodexEventHandler = class _CodexEventHandler {
24764
24783
  return await this.subagents.waitForMaterializedSession(childThreadId);
24765
24784
  }
24766
24785
  async waitForNativeSubagents(signal) {
24767
- await this.subagents.wait(signal);
24786
+ if (await this.subagents.wait(signal) === "timed_out") {
24787
+ await this.finishOutstandingNativeSubagents("failed");
24788
+ }
24768
24789
  }
24769
24790
  async finishOutstandingNativeSubagents(state) {
24791
+ await this.finishOutstandingCompactions(state === "cancelled" ? "cancelled" : "failed");
24770
24792
  await this.subagents.finishOutstanding(state);
24771
24793
  }
24794
+ async finishOutstandingCompactions(status, sessionId) {
24795
+ if (!this.supportsCompaction) return;
24796
+ for (const { sessionId: targetSessionId, update } of this.sessionState.compactions.finishOutstanding(status, sessionId)) {
24797
+ await this.session.update(update, targetSessionId);
24798
+ }
24799
+ }
24800
+ async finishCompactionsForNotification(notification) {
24801
+ if (!this.supportsCompaction) return;
24802
+ let updates;
24803
+ const sessionId = this.subagents.notificationSessionId(notification);
24804
+ if (notification.method === "turn/completed") {
24805
+ const turn = notification.params.turn;
24806
+ if (turn.status === "inProgress") return;
24807
+ updates = this.sessionState.compactions.finishTurn(
24808
+ sessionId,
24809
+ turn.id,
24810
+ turn.status === "interrupted" ? "cancelled" : "failed",
24811
+ turn.error?.message ?? "Codex ended the turn before compaction completed."
24812
+ );
24813
+ } else if (notification.method === "error" && !notification.params.willRetry) {
24814
+ updates = this.sessionState.compactions.finishTurn(
24815
+ sessionId,
24816
+ notification.params.turnId,
24817
+ "failed",
24818
+ notification.params.error.message
24819
+ );
24820
+ } else {
24821
+ return;
24822
+ }
24823
+ for (const update of updates) await this.session.update(update, sessionId);
24824
+ }
24772
24825
  async flushPendingPlanUpdates() {
24773
24826
  this.cancelPlanUpdateTimer();
24774
24827
  do {
@@ -24892,7 +24945,10 @@ var CodexEventHandler = class _CodexEventHandler {
24892
24945
  case "item/autoApprovalReview/completed":
24893
24946
  return this.handleGuardianApprovalReviewCompleted(notification.params);
24894
24947
  case "thread/compacted":
24895
- return this.createContextCompactedEvent();
24948
+ return this.supportsCompaction ? this.sessionState.compactions.completeLegacy(
24949
+ this.subagents.notificationSessionId(notification),
24950
+ notification.params.turnId
24951
+ ) : this.createContextCompactedEvent();
24896
24952
  case "item/reasoning/summaryTextDelta":
24897
24953
  this.completeRetryIncidentOnTurnProgress();
24898
24954
  return this.createReasoningDeltaEvent(notification.params);
@@ -24914,6 +24970,8 @@ var CodexEventHandler = class _CodexEventHandler {
24914
24970
  return this.createThreadGoalClearedEvent(notification.params);
24915
24971
  case "item/commandExecution/terminalInteraction":
24916
24972
  return this.createTerminalInteractionEvent(notification.params);
24973
+ case "thread/attachment/updated":
24974
+ return null;
24917
24975
  // ignored events
24918
24976
  case "thread/deleted":
24919
24977
  case "thread/reverted":
@@ -25069,7 +25127,7 @@ ${event.details}` : event.summary;
25069
25127
  this.terminalCommandIds.add(event.item.id);
25070
25128
  } else {
25071
25129
  this.terminalCommandIds.delete(event.item.id);
25072
- this.terminalCommandOutputIds.delete(event.item.id);
25130
+ this.commandOutputIds.delete(event.item.id);
25073
25131
  }
25074
25132
  return await createCommandExecutionUpdate(event.item);
25075
25133
  }
@@ -25091,7 +25149,11 @@ ${event.details}` : event.summary;
25091
25149
  this.rememberAgentMessagePhase(event.item);
25092
25150
  return null;
25093
25151
  case "contextCompaction":
25094
- return createContextCompactionStartUpdate(event.item);
25152
+ return this.supportsCompaction ? this.sessionState.compactions.start(
25153
+ this.subagents.notificationSessionId({ method: "item/started", params: event }),
25154
+ event.turnId,
25155
+ event.item.id
25156
+ ) : createContextCompactionStartUpdate(event.item);
25095
25157
  case "subAgentActivity":
25096
25158
  return this.subagents.legacyActivityStarted(event.item);
25097
25159
  case "sleep":
@@ -25159,7 +25221,11 @@ ${event.details}` : event.summary;
25159
25221
  case "exitedReviewMode":
25160
25222
  return this.createExitedReviewModeEvent(event.item);
25161
25223
  case "contextCompaction":
25162
- return createContextCompactionCompleteUpdate(event.item);
25224
+ return this.supportsCompaction ? this.sessionState.compactions.complete(
25225
+ this.subagents.notificationSessionId({ method: "item/completed", params: event }),
25226
+ event.turnId,
25227
+ event.item.id
25228
+ ) : createContextCompactionCompleteUpdate(event.item);
25163
25229
  //ignored types
25164
25230
  case "subAgentActivity":
25165
25231
  return this.subagents.legacyActivityCompleted(event.item);
@@ -25258,8 +25324,8 @@ ${event.details}` : event.summary;
25258
25324
  return createAgentTextMessageChunk("*Context compacted to fit the model's context window.*\n\n");
25259
25325
  }
25260
25326
  createCommandOutputDeltaEvent(event) {
25261
- if (this.terminalCommandIds.has(event.itemId) && event.delta.length > 0) {
25262
- this.terminalCommandOutputIds.add(event.itemId);
25327
+ if (event.delta.length > 0) {
25328
+ this.commandOutputIds.add(event.itemId);
25263
25329
  }
25264
25330
  return this.createCommandOutputEvent(event.itemId, event.delta, this.commandOutputMode(event.itemId));
25265
25331
  }
@@ -25335,28 +25401,32 @@ ${event.stdin}
25335
25401
  toolCallId: item.id,
25336
25402
  ...name === void 0 ? {} : { name },
25337
25403
  status: item.status === "completed" ? "completed" : "failed",
25338
- rawOutput: {
25339
- formatted_output: item.aggregatedOutput ?? "",
25340
- exit_code: item.exitCode
25404
+ ...this.sessionState.terminalOutputDeltaSupported ? {} : {
25405
+ rawOutput: {
25406
+ formatted_output: item.aggregatedOutput ?? "",
25407
+ exit_code: item.exitCode
25408
+ }
25341
25409
  }
25342
25410
  };
25343
25411
  const commandHadTerminal = this.terminalCommandIds.delete(item.id);
25344
- const commandHadOutput = this.terminalCommandOutputIds.delete(item.id);
25345
- if (!commandHadTerminal) {
25346
- return update;
25347
- }
25412
+ const commandHadOutput = this.commandOutputIds.delete(item.id);
25348
25413
  const terminalMeta = {};
25349
- if (!commandHadOutput && item.aggregatedOutput) {
25414
+ if (!commandHadOutput && item.aggregatedOutput && (commandHadTerminal || this.sessionState.terminalOutputDeltaSupported)) {
25350
25415
  Object.assign(
25351
25416
  terminalMeta,
25352
25417
  createTerminalOutputMeta(this.sessionState.terminalOutputMode, item.id, item.aggregatedOutput)
25353
25418
  );
25354
25419
  }
25355
- terminalMeta["terminal_exit"] = {
25356
- exit_code: item.exitCode,
25357
- signal: null,
25358
- terminal_id: item.id
25359
- };
25420
+ if (commandHadTerminal) {
25421
+ terminalMeta["terminal_exit"] = {
25422
+ exit_code: item.exitCode,
25423
+ signal: null,
25424
+ terminal_id: item.id
25425
+ };
25426
+ }
25427
+ if (Object.keys(terminalMeta).length === 0) {
25428
+ return update;
25429
+ }
25360
25430
  return {
25361
25431
  ...update,
25362
25432
  _meta: terminalMeta
@@ -27808,7 +27878,7 @@ var package_default = {
27808
27878
  publishConfig: {
27809
27879
  access: "public"
27810
27880
  },
27811
- version: "1.12.0",
27881
+ version: "1.12.1-preview.2",
27812
27882
  description: "",
27813
27883
  main: "dist/index.js",
27814
27884
  bin: {
@@ -27871,7 +27941,7 @@ var package_default = {
27871
27941
  },
27872
27942
  dependencies: {
27873
27943
  "@agentclientprotocol/sdk": "^1.4.0",
27874
- "@openai/codex": "^0.154.0",
27944
+ "@openai/codex": "^0.155.1",
27875
27945
  diff: "^9.0.0",
27876
27946
  open: "^11.0.1",
27877
27947
  "vscode-jsonrpc": "^9.0.1",
@@ -28637,8 +28707,9 @@ var CodexAcpClient = class {
28637
28707
  delivery: "inline"
28638
28708
  }, onTurnStarted);
28639
28709
  }
28640
- async runCompact(sessionId) {
28641
- await this.codexClient.runCompact({ threadId: sessionId });
28710
+ async runCompact(sessionId, onTurnStarted) {
28711
+ const completed = await this.codexClient.runCompact({ threadId: sessionId }, onTurnStarted);
28712
+ return completed.method === "turn/completed" ? completed.params : void 0;
28642
28713
  }
28643
28714
  async getGoal(sessionId) {
28644
28715
  const response = await this.codexClient.threadGoalGet({ threadId: sessionId });
@@ -29242,7 +29313,7 @@ var CodexAppServerClient = class {
29242
29313
  if (this.handleStaleTurnNotification(serverNotification, routing)) {
29243
29314
  return;
29244
29315
  }
29245
- this.recordTurnRouting(routing);
29316
+ this.recordTurnRouting(routing, serverNotification);
29246
29317
  if (this.handleStaleTurnNotification(serverNotification, routing)) {
29247
29318
  return;
29248
29319
  }
@@ -29524,10 +29595,45 @@ var CodexAppServerClient = class {
29524
29595
  threadStatusChanged: handleThreadStatusChanged
29525
29596
  };
29526
29597
  }
29527
- async runCompact(params) {
29528
- const compactionCompleted = this.awaitCompactionCompleted(params.threadId);
29529
- await this.threadCompactStart(params);
29530
- return await compactionCompleted;
29598
+ async runCompact(params, onTurnStarted) {
29599
+ let compactTurnId = null;
29600
+ let resolveCompleted = () => {
29601
+ };
29602
+ let rejectCompleted = () => {
29603
+ };
29604
+ const completed = new Promise((resolve, reject) => {
29605
+ resolveCompleted = resolve;
29606
+ rejectCompleted = reject;
29607
+ });
29608
+ void completed.catch(() => {
29609
+ });
29610
+ const closed = this.connection.onClose?.(() => rejectCompleted(new Error("Codex connection closed during compaction.")));
29611
+ const completeCompaction = (event) => {
29612
+ if (compactTurnId !== null && event.params.turnId !== compactTurnId) return;
29613
+ resolveCompleted(event);
29614
+ };
29615
+ const releaseCompactionCapture = this.captureCompactionCompletions(params.threadId, completeCompaction);
29616
+ const releaseTurnCapture = this.captureTurnCompletions(params.threadId, (event) => {
29617
+ if (compactTurnId === null || event.turn.id !== compactTurnId) return;
29618
+ if (event.turn.status !== "inProgress") {
29619
+ resolveCompleted({ method: "turn/completed", params: event });
29620
+ }
29621
+ });
29622
+ const releaseRoutingCapture = this.captureTurnRoutings(params.threadId, (turnId, notification) => {
29623
+ if (compactTurnId !== null) return;
29624
+ if (notification.method !== "turn/started" && !(notification.method === "item/started" && notification.params.item.type === "contextCompaction")) return;
29625
+ compactTurnId = turnId;
29626
+ onTurnStarted?.(turnId);
29627
+ });
29628
+ try {
29629
+ await this.threadCompactStart(params);
29630
+ return await completed;
29631
+ } finally {
29632
+ releaseTurnCapture();
29633
+ releaseRoutingCapture();
29634
+ releaseCompactionCapture();
29635
+ closed?.dispose();
29636
+ }
29531
29637
  }
29532
29638
  async turnInterrupt(params) {
29533
29639
  return await this.sendRequest({ method: "turn/interrupt", params });
@@ -29697,9 +29803,10 @@ var CodexAppServerClient = class {
29697
29803
  }
29698
29804
  async awaitCompactionCompleted(threadId) {
29699
29805
  return await new Promise((resolve) => {
29700
- const resolvers = this.pendingCompactionCompletionResolvers.get(threadId) ?? /* @__PURE__ */ new Set();
29701
- resolvers.add(resolve);
29702
- this.pendingCompactionCompletionResolvers.set(threadId, resolvers);
29806
+ const releaseCapture = this.captureCompactionCompletions(threadId, (event) => {
29807
+ releaseCapture();
29808
+ resolve(event);
29809
+ });
29703
29810
  });
29704
29811
  }
29705
29812
  resolveTurnInterrupted(threadId, turnId) {
@@ -29779,11 +29886,24 @@ var CodexAppServerClient = class {
29779
29886
  if (!resolvers) {
29780
29887
  return;
29781
29888
  }
29782
- this.pendingCompactionCompletionResolvers.delete(threadId);
29783
29889
  for (const resolve of resolvers) {
29784
29890
  resolve(event);
29785
29891
  }
29786
29892
  }
29893
+ captureCompactionCompletions(threadId, capture) {
29894
+ const captures = this.pendingCompactionCompletionResolvers.get(threadId) ?? /* @__PURE__ */ new Set();
29895
+ captures.add(capture);
29896
+ this.pendingCompactionCompletionResolvers.set(threadId, captures);
29897
+ let released = false;
29898
+ return () => {
29899
+ if (released) return;
29900
+ released = true;
29901
+ captures.delete(capture);
29902
+ if (captures.size === 0) {
29903
+ this.pendingCompactionCompletionResolvers.delete(threadId);
29904
+ }
29905
+ };
29906
+ }
29787
29907
  recordThreadStatusChanged(event) {
29788
29908
  const captures = this.threadStatusCaptures.get(event.threadId);
29789
29909
  if (!captures) {
@@ -29811,7 +29931,7 @@ var CodexAppServerClient = class {
29811
29931
  capture();
29812
29932
  }
29813
29933
  }
29814
- recordTurnRouting(routing) {
29934
+ recordTurnRouting(routing, notification) {
29815
29935
  if (routing.threadId === null || routing.turnId === null) {
29816
29936
  return;
29817
29937
  }
@@ -29820,7 +29940,7 @@ var CodexAppServerClient = class {
29820
29940
  return;
29821
29941
  }
29822
29942
  for (const capture of captures) {
29823
- capture(routing.turnId);
29943
+ capture(routing.turnId, notification);
29824
29944
  }
29825
29945
  }
29826
29946
  handleStaleTurnNotification(notification, routing) {
@@ -30267,8 +30387,12 @@ var CodexCommands = class {
30267
30387
  return { handled: options.setConfigOption !== void 0 };
30268
30388
  }
30269
30389
  case "compact": {
30270
- await this.runWithProcessCheck(() => this.codexAcpClient.runCompact(sessionId));
30271
- return { handled: true };
30390
+ options.onTurnStartPending?.();
30391
+ const turnCompleted = await this.runWithProcessCheck(() => this.codexAcpClient.runCompact(
30392
+ sessionId,
30393
+ (turnId) => options.onTurnStarted?.(turnId, sessionId)
30394
+ ));
30395
+ return { handled: true, ...turnCompleted === void 0 ? {} : { turnCompleted } };
30272
30396
  }
30273
30397
  case "goal": {
30274
30398
  return await this.runGoalCommand(sessionState, command.rest, options);
@@ -32233,6 +32357,72 @@ function notificationThreadId(notification) {
32233
32357
  return typeof threadId === "string" ? threadId : null;
32234
32358
  }
32235
32359
 
32360
+ // src/CodexSessionCompactions.ts
32361
+ function clientSupportsCompaction(capabilities) {
32362
+ return capabilities?.session?.compaction != null;
32363
+ }
32364
+ function createCompactionUpdate(compactionId, status, error51) {
32365
+ return {
32366
+ sessionUpdate: "compaction_update",
32367
+ compactionId,
32368
+ status,
32369
+ ...status === "failed" && error51 !== void 0 ? { error: error51 } : {}
32370
+ };
32371
+ }
32372
+ var CodexSessionCompactions = class {
32373
+ items = /* @__PURE__ */ new Map();
32374
+ latestByTurn = /* @__PURE__ */ new Map();
32375
+ start(sessionId, turnId, itemId) {
32376
+ const key = JSON.stringify([sessionId, itemId]);
32377
+ if (this.items.has(key)) return null;
32378
+ const compaction = this.remember(sessionId, turnId, itemId);
32379
+ return createCompactionUpdate(compaction.id, "in_progress");
32380
+ }
32381
+ complete(sessionId, turnId, itemId) {
32382
+ const latest = this.latestByTurn.get(JSON.stringify([sessionId, turnId]));
32383
+ if (!this.items.has(JSON.stringify([sessionId, itemId])) && latest?.legacyOnly) {
32384
+ this.items.delete(JSON.stringify([sessionId, latest.id]));
32385
+ this.items.set(JSON.stringify([sessionId, itemId]), latest);
32386
+ latest.legacyOnly = false;
32387
+ }
32388
+ const compaction = this.items.get(JSON.stringify([sessionId, itemId])) ?? this.remember(sessionId, turnId, itemId);
32389
+ return this.finish(compaction, "completed");
32390
+ }
32391
+ completeLegacy(sessionId, turnId) {
32392
+ const compaction = this.latestByTurn.get(JSON.stringify([sessionId, turnId])) ?? this.remember(sessionId, turnId, `compaction:${turnId}`, true);
32393
+ return this.finish(compaction, "completed");
32394
+ }
32395
+ finishTurn(sessionId, turnId, status, error51) {
32396
+ const updates = [];
32397
+ for (const compaction of this.items.values()) {
32398
+ if (compaction.sessionId !== sessionId || compaction.turnId !== turnId) continue;
32399
+ const update = this.finish(compaction, status, error51);
32400
+ if (update) updates.push(update);
32401
+ }
32402
+ return updates;
32403
+ }
32404
+ finishOutstanding(status, sessionId) {
32405
+ const updates = [];
32406
+ for (const compaction of this.items.values()) {
32407
+ if (sessionId !== void 0 && compaction.sessionId !== sessionId) continue;
32408
+ const update = this.finish(compaction, status);
32409
+ if (update) updates.push({ sessionId: compaction.sessionId, update });
32410
+ }
32411
+ return updates;
32412
+ }
32413
+ remember(sessionId, turnId, id, legacyOnly = false) {
32414
+ const compaction = { sessionId, turnId, id, terminal: false, legacyOnly };
32415
+ this.items.set(JSON.stringify([sessionId, id]), compaction);
32416
+ this.latestByTurn.set(JSON.stringify([sessionId, turnId]), compaction);
32417
+ return compaction;
32418
+ }
32419
+ finish(compaction, status, error51) {
32420
+ if (compaction.terminal) return null;
32421
+ compaction.terminal = true;
32422
+ return createCompactionUpdate(compaction.id, status, error51);
32423
+ }
32424
+ };
32425
+
32236
32426
  // src/CodexAcpServer.ts
32237
32427
  var CODEX_PROCESS_EXITED_ERROR_CODE = 1001;
32238
32428
  function clientSupportsTypedSessionFailures(capabilities) {
@@ -32252,6 +32442,7 @@ var CodexAcpServer = class {
32252
32442
  clientInfo;
32253
32443
  clientCapabilities;
32254
32444
  terminalOutputMode;
32445
+ terminalOutputDeltaSupported;
32255
32446
  booleanConfigOptionsSupported;
32256
32447
  /** Last `authStatus` pushed to the client; used to suppress duplicates. */
32257
32448
  currentAuthStatus;
@@ -32291,6 +32482,7 @@ var CodexAcpServer = class {
32291
32482
  this.clientInfo = null;
32292
32483
  this.clientCapabilities = null;
32293
32484
  this.terminalOutputMode = "terminal_output_delta";
32485
+ this.terminalOutputDeltaSupported = false;
32294
32486
  this.booleanConfigOptionsSupported = false;
32295
32487
  this.currentAuthStatus = null;
32296
32488
  this.availableCommands = this.createAvailableCommands(codexAcpClient);
@@ -32310,6 +32502,7 @@ var CodexAcpServer = class {
32310
32502
  this.clientCapabilities = _params.clientCapabilities ?? null;
32311
32503
  this.initializeRequest = _params;
32312
32504
  this.terminalOutputMode = resolveTerminalOutputMode(_params.clientCapabilities);
32505
+ this.terminalOutputDeltaSupported = clientSupportsTerminalOutputDelta(_params.clientCapabilities);
32313
32506
  this.booleanConfigOptionsSupported = clientSupportsBooleanConfigOptions(_params.clientCapabilities);
32314
32507
  await this.runWithProcessCheck(() => this.codexAcpClient.initialize(_params));
32315
32508
  this.publishFirstAuthStatusAfterResponse();
@@ -32638,6 +32831,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
32638
32831
  currentModelSupportsFast,
32639
32832
  sessionMcpServers,
32640
32833
  terminalOutputMode: this.terminalOutputMode,
32834
+ terminalOutputDeltaSupported: this.terminalOutputDeltaSupported,
32641
32835
  goalRevision: 0,
32642
32836
  sessionTitle: null,
32643
32837
  sessionTitleSource: operation === "resume" ? "unknown" : "unset",
@@ -32646,7 +32840,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
32646
32840
  clientSupportsSubagents(this.clientCapabilities),
32647
32841
  new ACPSessionConnection(this.connection, sessionId)
32648
32842
  ),
32649
- asyncTasks: this.createAsyncTasks(sessionId)
32843
+ asyncTasks: this.createAsyncTasks(sessionId),
32844
+ compactions: new CodexSessionCompactions()
32650
32845
  };
32651
32846
  sessionState.titleGen = new TitleGenerator(
32652
32847
  this.codexAcpClient.appServerClient,
@@ -33698,6 +33893,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
33698
33893
  currentModelSupportsFast,
33699
33894
  sessionMcpServers,
33700
33895
  terminalOutputMode: this.terminalOutputMode,
33896
+ terminalOutputDeltaSupported: this.terminalOutputDeltaSupported,
33701
33897
  goalRevision: 0,
33702
33898
  sessionTitle: null,
33703
33899
  sessionTitleSource: "unset",
@@ -33706,7 +33902,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
33706
33902
  clientSupportsSubagents(this.clientCapabilities),
33707
33903
  new ACPSessionConnection(this.connection, sessionId)
33708
33904
  ),
33709
- asyncTasks: this.createAsyncTasks(sessionId)
33905
+ asyncTasks: this.createAsyncTasks(sessionId),
33906
+ compactions: new CodexSessionCompactions()
33710
33907
  };
33711
33908
  sessionState.titleGen = new TitleGenerator(
33712
33909
  this.codexAcpClient.appServerClient,
@@ -33981,7 +34178,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
33981
34178
  case "exitedReviewMode":
33982
34179
  return [this.createReviewModeUpdate(item, false)];
33983
34180
  case "contextCompaction":
33984
- return [createCompletedContextCompactionUpdate(item)];
34181
+ return [clientSupportsCompaction(this.clientCapabilities) ? createCompactionUpdate(item.id, "completed") : createCompletedContextCompactionUpdate(item)];
33985
34182
  case "plan":
33986
34183
  return item.text.length > 0 ? [this.createPlanHistoryUpdate(item)] : [];
33987
34184
  }
@@ -34417,7 +34614,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
34417
34614
  this.sessionFailureEpoch,
34418
34615
  sessionState.subagents,
34419
34616
  (accountUpdated) => this.handleAccountUpdated(accountUpdated),
34420
- agentFileChangeReportRequest !== null
34617
+ agentFileChangeReportRequest !== null,
34618
+ clientSupportsCompaction(this.clientCapabilities)
34421
34619
  );
34422
34620
  eventHandler = promptEventHandler;
34423
34621
  const permissionLifecycle = this.permissionLifecycleContext(sessionState);
@@ -34767,7 +34965,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
34767
34965
  promptWasCancelled || activePrompt.signal.aborted || this.sessionIsClosing(params.sessionId) ? "cancelled" : "failed"
34768
34966
  );
34769
34967
  } catch (error51) {
34770
- logger.error("Failed to publish terminal subagent state during prompt cleanup", error51);
34968
+ logger.error("Failed to publish terminal compaction or subagent state during prompt cleanup", error51);
34771
34969
  }
34772
34970
  if (agentFileChangeReportRequest !== null && agentFileChangeWorkspace !== null) {
34773
34971
  if (promptWasCancelled || activePrompt.signal.aborted || this.sessionIsClosing(params.sessionId)) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.12.0",
6
+ "version": "1.12.1-preview.2",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@agentclientprotocol/sdk": "^1.4.0",
69
- "@openai/codex": "^0.154.0",
69
+ "@openai/codex": "^0.155.1",
70
70
  "diff": "^9.0.0",
71
71
  "open": "^11.0.1",
72
72
  "vscode-jsonrpc": "^9.0.1",