@agentconnect.md/codex-acp 1.1.9-agentconnect.1 → 1.3.0-agentconnect.1

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 (3) hide show
  1. package/README.md +2 -1
  2. package/dist/index.js +883 -176
  3. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -3453,7 +3453,7 @@ var require_main = __commonJS({
3453
3453
  exports.createMessageConnection = createMessageConnection2;
3454
3454
  var ril_1 = __importDefault(require_ril());
3455
3455
  ril_1.default.install();
3456
- var path6 = __importStar(__require("path"));
3456
+ var path7 = __importStar(__require("path"));
3457
3457
  var os2 = __importStar(__require("os"));
3458
3458
  var fs7 = __importStar(__require("fs"));
3459
3459
  var crypto_1 = __require("crypto");
@@ -3605,7 +3605,7 @@ var require_main = __commonJS({
3605
3605
  throw new Error(`Unable to generate a random pipe name with ${randomLength} characters.`);
3606
3606
  }
3607
3607
  const randomSuffix = (0, crypto_1.randomBytes)(Math.floor(randomLength / 2)).toString("hex");
3608
- return path6.join(tmpDir, `lsp-${randomSuffix}.sock`);
3608
+ return path7.join(tmpDir, `lsp-${randomSuffix}.sock`);
3609
3609
  }
3610
3610
  function createClientPipeTransport(pipeName, encoding = "utf-8") {
3611
3611
  let connectResolve;
@@ -4509,10 +4509,10 @@ function mergeDefs(...defs) {
4509
4509
  function cloneDef(schema) {
4510
4510
  return mergeDefs(schema._zod.def);
4511
4511
  }
4512
- function getElementAtPath(obj, path6) {
4513
- if (!path6)
4512
+ function getElementAtPath(obj, path7) {
4513
+ if (!path7)
4514
4514
  return obj;
4515
- return path6.reduce((acc, key) => acc?.[key], obj);
4515
+ return path7.reduce((acc, key) => acc?.[key], obj);
4516
4516
  }
4517
4517
  function promiseAllObject(promisesObj) {
4518
4518
  const keys = Object.keys(promisesObj);
@@ -4921,11 +4921,11 @@ function explicitlyAborted(x, startIndex = 0) {
4921
4921
  }
4922
4922
  return false;
4923
4923
  }
4924
- function prefixIssues(path6, issues) {
4924
+ function prefixIssues(path7, issues) {
4925
4925
  return issues.map((iss) => {
4926
4926
  var _a3;
4927
4927
  (_a3 = iss).path ?? (_a3.path = []);
4928
- iss.path.unshift(path6);
4928
+ iss.path.unshift(path7);
4929
4929
  return iss;
4930
4930
  });
4931
4931
  }
@@ -5072,16 +5072,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
5072
5072
  }
5073
5073
  function formatError(error51, mapper = (issue2) => issue2.message) {
5074
5074
  const fieldErrors = { _errors: [] };
5075
- const processError = (error52, path6 = []) => {
5075
+ const processError = (error52, path7 = []) => {
5076
5076
  for (const issue2 of error52.issues) {
5077
5077
  if (issue2.code === "invalid_union" && issue2.errors.length) {
5078
- issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
5078
+ issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
5079
5079
  } else if (issue2.code === "invalid_key") {
5080
- processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
5080
+ processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
5081
5081
  } else if (issue2.code === "invalid_element") {
5082
- processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
5082
+ processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
5083
5083
  } else {
5084
- const fullpath = [...path6, ...issue2.path];
5084
+ const fullpath = [...path7, ...issue2.path];
5085
5085
  if (fullpath.length === 0) {
5086
5086
  fieldErrors._errors.push(mapper(issue2));
5087
5087
  } else {
@@ -5108,17 +5108,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
5108
5108
  }
5109
5109
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
5110
5110
  const result = { errors: [] };
5111
- const processError = (error52, path6 = []) => {
5111
+ const processError = (error52, path7 = []) => {
5112
5112
  var _a3, _b;
5113
5113
  for (const issue2 of error52.issues) {
5114
5114
  if (issue2.code === "invalid_union" && issue2.errors.length) {
5115
- issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
5115
+ issue2.errors.map((issues) => processError({ issues }, [...path7, ...issue2.path]));
5116
5116
  } else if (issue2.code === "invalid_key") {
5117
- processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
5117
+ processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
5118
5118
  } else if (issue2.code === "invalid_element") {
5119
- processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
5119
+ processError({ issues: issue2.issues }, [...path7, ...issue2.path]);
5120
5120
  } else {
5121
- const fullpath = [...path6, ...issue2.path];
5121
+ const fullpath = [...path7, ...issue2.path];
5122
5122
  if (fullpath.length === 0) {
5123
5123
  result.errors.push(mapper(issue2));
5124
5124
  continue;
@@ -5150,8 +5150,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
5150
5150
  }
5151
5151
  function toDotPath(_path) {
5152
5152
  const segs = [];
5153
- const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5154
- for (const seg of path6) {
5153
+ const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
5154
+ for (const seg of path7) {
5155
5155
  if (typeof seg === "number")
5156
5156
  segs.push(`[${seg}]`);
5157
5157
  else if (typeof seg === "symbol")
@@ -17843,13 +17843,13 @@ function resolveRef(ref, ctx) {
17843
17843
  if (!ref.startsWith("#")) {
17844
17844
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
17845
17845
  }
17846
- const path6 = ref.slice(1).split("/").filter(Boolean);
17847
- if (path6.length === 0) {
17846
+ const path7 = ref.slice(1).split("/").filter(Boolean);
17847
+ if (path7.length === 0) {
17848
17848
  return ctx.rootSchema;
17849
17849
  }
17850
17850
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
17851
- if (path6[0] === defsKey) {
17852
- const key = path6[1];
17851
+ if (path7[0] === defsKey) {
17852
+ const key = path7[1];
17853
17853
  if (!key || !ctx.defs[key]) {
17854
17854
  throw new Error(`Reference not found: ${ref}`);
17855
17855
  }
@@ -22787,8 +22787,20 @@ function createTerminalOutputMeta(mode, terminalId, data) {
22787
22787
  }
22788
22788
  }
22789
22789
 
22790
+ // src/ContextCompactionMeta.ts
22791
+ var CONTEXT_COMPACTION_META_KEY = "contextCompaction";
22792
+ var CONTEXT_COMPACTION_META_VERSION = 1;
22793
+ function createContextCompactionMeta(metadata = {}) {
22794
+ return {
22795
+ [CONTEXT_COMPACTION_META_KEY]: {
22796
+ version: CONTEXT_COMPACTION_META_VERSION,
22797
+ ...metadata
22798
+ }
22799
+ };
22800
+ }
22801
+
22790
22802
  // src/CodexToolCallMapper.ts
22791
- var CONTEXT_COMPACTION_META = { contextCompaction: true };
22803
+ var CONTEXT_COMPACTION_META = createContextCompactionMeta();
22792
22804
  function toAcpStatus(status) {
22793
22805
  switch (status) {
22794
22806
  case "inProgress":
@@ -22935,8 +22947,8 @@ function createContextCompactionStartUpdate(item) {
22935
22947
  return {
22936
22948
  sessionUpdate: "tool_call",
22937
22949
  toolCallId: item.id,
22938
- kind: "other",
22939
- title: "Context compacting",
22950
+ kind: "think",
22951
+ title: "Compact conversation",
22940
22952
  status: "in_progress",
22941
22953
  _meta: CONTEXT_COMPACTION_META
22942
22954
  };
@@ -22945,7 +22957,7 @@ function createContextCompactionCompleteUpdate(item) {
22945
22957
  return {
22946
22958
  sessionUpdate: "tool_call_update",
22947
22959
  toolCallId: item.id,
22948
- title: "Context compacted",
22960
+ title: "Compact conversation",
22949
22961
  status: "completed",
22950
22962
  _meta: CONTEXT_COMPACTION_META
22951
22963
  };
@@ -22954,8 +22966,8 @@ function createCompletedContextCompactionUpdate(item) {
22954
22966
  return {
22955
22967
  sessionUpdate: "tool_call",
22956
22968
  toolCallId: item.id,
22957
- kind: "other",
22958
- title: "Context compacted",
22969
+ kind: "think",
22970
+ title: "Compact conversation",
22959
22971
  status: "completed",
22960
22972
  _meta: CONTEXT_COMPACTION_META
22961
22973
  };
@@ -23245,13 +23257,13 @@ function createTerminalCommandEvent(event, terminalId, cwd) {
23245
23257
  }
23246
23258
  };
23247
23259
  }
23248
- function createSearchTitle(query, path6) {
23249
- if (query && path6) {
23250
- return `Search for '${query}' in ${path6}`;
23260
+ function createSearchTitle(query, path7) {
23261
+ if (query && path7) {
23262
+ return `Search for '${query}' in ${path7}`;
23251
23263
  } else if (query) {
23252
23264
  return `Search for '${query}'`;
23253
- } else if (path6) {
23254
- return `Search in '${path6}'`;
23265
+ } else if (path7) {
23266
+ return `Search in '${path7}'`;
23255
23267
  }
23256
23268
  return "Search";
23257
23269
  }
@@ -23477,12 +23489,12 @@ function revertPatch(unifiedDiff) {
23477
23489
  if (!patch) return null;
23478
23490
  return reversePatch(patch);
23479
23491
  }
23480
- function createUpdateDiffContent(path6, oldText, newText) {
23492
+ function createUpdateDiffContent(path7, oldText, newText) {
23481
23493
  return {
23482
23494
  type: "diff",
23483
23495
  oldText,
23484
23496
  newText,
23485
- path: path6,
23497
+ path: path7,
23486
23498
  _meta: {
23487
23499
  kind: "update"
23488
23500
  }
@@ -23566,22 +23578,37 @@ function createAgentTextThoughtChunk(text, messageId, meta3) {
23566
23578
  return createAgentThoughtChunk({ type: "text", text }, messageId, meta3);
23567
23579
  }
23568
23580
 
23569
- // src/AcpExtensions.ts
23570
- var LEGACY_SET_SESSION_MODEL_METHOD = "session/set_model";
23571
- var SESSION_STEERING_METHOD = "_session/steering";
23572
- var GOAL_CONTROL_METHOD = "_codex/session/goal_control";
23573
- function isExtMethodRequest(request) {
23574
- return request.method === "authentication/status" || request.method === "authentication/logout" || request.method === LEGACY_SET_SESSION_MODEL_METHOD || request.method === GOAL_CONTROL_METHOD || request.method === SESSION_STEERING_METHOD;
23575
- }
23581
+ // src/GoalExtension.ts
23582
+ var GOAL_EXTENSION_VERSION = 1;
23583
+ var GOAL_CONTROL_METHOD = "_session/goal";
23584
+ var LEGACY_GOAL_CONTROL_METHOD = "_codex/session/goal_control";
23585
+ var GOAL_CONTROL_ACTIONS = ["set", "pause", "resume", "clear"];
23576
23586
 
23577
23587
  // src/ThreadGoalSnapshot.ts
23588
+ function toGoalStatus(status) {
23589
+ switch (status) {
23590
+ case "active":
23591
+ case "paused":
23592
+ case "blocked":
23593
+ case "complete":
23594
+ return status;
23595
+ case "usageLimited":
23596
+ case "budgetLimited":
23597
+ return "limited";
23598
+ }
23599
+ }
23600
+ function toUnixMilliseconds(timestampSeconds) {
23601
+ return timestampSeconds * 1e3;
23602
+ }
23578
23603
  function toThreadGoalSnapshot(goal) {
23579
23604
  return {
23580
23605
  objective: goal.objective.trim(),
23581
- status: goal.status,
23606
+ status: toGoalStatus(goal.status),
23582
23607
  tokenBudget: goal.tokenBudget,
23608
+ tokensUsed: goal.tokensUsed,
23583
23609
  timeUsedSeconds: goal.timeUsedSeconds,
23584
- createdAt: goal.createdAt,
23610
+ createdAt: toUnixMilliseconds(goal.createdAt),
23611
+ updatedAt: toUnixMilliseconds(goal.updatedAt),
23585
23612
  controlMethod: GOAL_CONTROL_METHOD
23586
23613
  };
23587
23614
  }
@@ -23592,10 +23619,104 @@ function sameThreadGoalSnapshot(left, right) {
23592
23619
  }
23593
23620
 
23594
23621
  // src/CodexEventHandler.ts
23622
+ import { randomUUID } from "node:crypto";
23623
+
23624
+ // src/AirExtension.ts
23625
+ var JETBRAINS_META_KEY = "jetbrains";
23626
+ var AIR_META_KEY = "air";
23627
+ var AIR_EXTENSION_VERSION_KEY = "version";
23628
+ var AIR_EXTENSION_CAPABILITIES_KEY = "capabilities";
23629
+ var AIR_SESSION_FAILURE_KEY = "sessionFailure";
23630
+ var AIR_EXTENSION_VERSION = 1;
23631
+
23632
+ // src/CodexEventHandler.ts
23633
+ var MAX_SESSION_FAILURE_TITLE_LENGTH = 240;
23634
+ var SESSION_FAILURE_POLICY = {
23635
+ transport_lost: {
23636
+ category: "connection",
23637
+ actions: ["retry", "new_session"]
23638
+ },
23639
+ auth_required: {
23640
+ category: "access",
23641
+ actions: ["login"]
23642
+ },
23643
+ rate_limited: {
23644
+ category: "limit",
23645
+ actions: ["retry"]
23646
+ },
23647
+ quota_exhausted: {
23648
+ category: "limit",
23649
+ actions: []
23650
+ },
23651
+ overloaded: {
23652
+ category: "service",
23653
+ actions: ["retry"]
23654
+ },
23655
+ context_exhausted: {
23656
+ category: "limit",
23657
+ actions: ["new_session"]
23658
+ },
23659
+ budget_exhausted: {
23660
+ category: "limit",
23661
+ actions: ["new_session"]
23662
+ },
23663
+ policy_denied: {
23664
+ category: "request",
23665
+ actions: []
23666
+ },
23667
+ bad_request: {
23668
+ category: "request",
23669
+ actions: []
23670
+ },
23671
+ provider_error: {
23672
+ category: "service",
23673
+ actions: ["retry"]
23674
+ },
23675
+ internal_error: {
23676
+ category: "service",
23677
+ actions: ["retry", "new_session"]
23678
+ }
23679
+ };
23680
+ var SYNTHETIC_FAILURE_TITLE = {
23681
+ transport_lost: "Connection to Codex was lost.",
23682
+ internal_error: "Codex encountered an internal error."
23683
+ };
23684
+ function nextSessionFailureRevision(previous, id) {
23685
+ return previous?.id === id ? previous.revision + 1 : 1;
23686
+ }
23687
+ var STRING_CODEX_ERROR_CATEGORIES = {
23688
+ contextWindowExceeded: "context_exhausted",
23689
+ sessionBudgetExceeded: "budget_exhausted",
23690
+ usageLimitExceeded: "quota_exhausted",
23691
+ serverOverloaded: "overloaded",
23692
+ cyberPolicy: "policy_denied",
23693
+ internalServerError: "internal_error",
23694
+ unauthorized: "auth_required",
23695
+ badRequest: "bad_request",
23696
+ threadRollbackFailed: "provider_error",
23697
+ sandboxError: "provider_error",
23698
+ other: "provider_error"
23699
+ };
23700
+ var STRUCTURED_CODEX_ERROR_CATEGORIES = {
23701
+ httpConnectionFailed: "transport_lost",
23702
+ responseStreamConnectionFailed: "transport_lost",
23703
+ responseStreamDisconnected: "transport_lost",
23704
+ responseTooManyFailedAttempts: "transport_lost",
23705
+ activeTurnNotSteerable: "provider_error"
23706
+ };
23595
23707
  var CodexEventHandler = class _CodexEventHandler {
23596
23708
  static PLAN_UPDATE_INTERVAL_MS = 150;
23597
23709
  sessionState;
23598
23710
  supportsPlanUpdates;
23711
+ supportsTypedSessionFailures;
23712
+ sessionFailureEpoch;
23713
+ pendingErrors = [];
23714
+ failuresById = /* @__PURE__ */ new Map();
23715
+ activeFailureIdByScope = /* @__PURE__ */ new Map();
23716
+ failureTurnIdById = /* @__PURE__ */ new Map();
23717
+ allocatedFailureScopes = /* @__PURE__ */ new Set();
23718
+ lastSessionNotice;
23719
+ nextNoticeId = 1;
23599
23720
  failure = null;
23600
23721
  completedPlan = null;
23601
23722
  activeFuzzyFileSearchSessions = /* @__PURE__ */ new Set();
@@ -23614,20 +23735,113 @@ var CodexEventHandler = class _CodexEventHandler {
23614
23735
  terminalCommandOutputIds = /* @__PURE__ */ new Set();
23615
23736
  agentMessagePhases = /* @__PURE__ */ new Map();
23616
23737
  activeSubAgentActivities = /* @__PURE__ */ new Set();
23617
- constructor(connection, sessionState, supportsPlanUpdates = false) {
23738
+ constructor(connection, sessionState, supportsPlanUpdates = false, supportsTypedSessionFailures = false, sessionFailureEpoch = randomUUID()) {
23618
23739
  this.sessionState = sessionState;
23619
23740
  this.supportsPlanUpdates = supportsPlanUpdates;
23741
+ this.supportsTypedSessionFailures = supportsTypedSessionFailures;
23742
+ this.sessionFailureEpoch = sessionFailureEpoch;
23620
23743
  this.session = new ACPSessionConnection(connection, sessionState.sessionId);
23744
+ if (sessionState.sessionFailure !== void 0) {
23745
+ this.failuresById.set(sessionState.sessionFailure.id, sessionState.sessionFailure);
23746
+ }
23621
23747
  }
23622
23748
  getFailure() {
23623
23749
  return this.failure;
23624
23750
  }
23751
+ getTerminalSessionFailureMeta(turnId, allowUnattributed = false) {
23752
+ const failure = this.sessionState.sessionFailure;
23753
+ if (!this.supportsTypedSessionFailures || failure === void 0 || (this.failureTurnIdById.get(failure.id) === void 0 ? !allowUnattributed : turnId === null || this.failureTurnIdById.get(failure.id) !== turnId)) {
23754
+ return null;
23755
+ }
23756
+ return this.createSessionFailureMeta(failure);
23757
+ }
23758
+ recordSyntheticTerminalFailure(kind, turnId) {
23759
+ this.recordSessionFailure(kind, turnId ?? void 0, "error", SYNTHETIC_FAILURE_TITLE[kind]);
23760
+ }
23761
+ /**
23762
+ * Handles notifications after the prompt-local handler has been disposed. The app-server subscription
23763
+ * remains installed until the ACP session closes, so terminal errors need a durable session-level path
23764
+ * instead of entering a turn buffer that will never be flushed.
23765
+ */
23766
+ async handleSessionScopedNotification(notification) {
23767
+ if (notification.method !== "error") {
23768
+ await this.handleNotification(notification);
23769
+ return;
23770
+ }
23771
+ if (!this.supportsTypedSessionFailures) {
23772
+ await this.handleNotification(notification);
23773
+ return;
23774
+ }
23775
+ if (notification.params.willRetry) {
23776
+ await this.session.update(this.createSessionFailureUpdate(this.recordRetryWarning(notification.params, false)));
23777
+ return;
23778
+ }
23779
+ const failure = this.recordSessionFailure(
23780
+ this.sessionFailureKind(notification.params.error.codexErrorInfo),
23781
+ notification.params.turnId,
23782
+ "error",
23783
+ notification.params.error.message,
23784
+ void 0,
23785
+ false
23786
+ );
23787
+ await this.session.update(this.createSessionFailureUpdate(failure));
23788
+ }
23789
+ async flushPendingErrors() {
23790
+ if (this.sessionState.currentTurnId === null || this.pendingErrors.length === 0) {
23791
+ return;
23792
+ }
23793
+ const errors = this.pendingErrors.splice(0);
23794
+ for (const error51 of errors) {
23795
+ const update = await this.createErrorEvent(error51);
23796
+ if (update) {
23797
+ await this.session.update(update);
23798
+ }
23799
+ }
23800
+ }
23801
+ async flushPendingErrorsAsSessionScoped() {
23802
+ if (!this.supportsTypedSessionFailures || this.pendingErrors.length === 0) {
23803
+ return;
23804
+ }
23805
+ const errors = this.pendingErrors.splice(0);
23806
+ for (const error51 of errors) {
23807
+ await this.handleSessionScopedNotification({ method: "error", params: error51 });
23808
+ }
23809
+ }
23810
+ async clearSessionFailure() {
23811
+ delete this.sessionState.sessionFailure;
23812
+ }
23813
+ async completeSuccessfulTurn(turnId) {
23814
+ this.lastSessionNotice = void 0;
23815
+ if (!this.supportsTypedSessionFailures || turnId === null) return;
23816
+ const active = this.sessionState.sessionFailure;
23817
+ if (active?.id !== this.activeFailureIdByScope.get(turnId) || active?.severity !== "warning") return;
23818
+ this.activeFailureIdByScope.delete(turnId);
23819
+ delete this.sessionState.sessionFailure;
23820
+ }
23821
+ async handleFailedTurn(turn) {
23822
+ const activeFailure = this.sessionState.sessionFailure;
23823
+ if (!this.supportsTypedSessionFailures || turn.status !== "failed" || this.failure !== null || this.failureTurnIdById.get(activeFailure?.id ?? "") === turn.id && activeFailure?.severity === "error") {
23824
+ return;
23825
+ }
23826
+ const error51 = turn.error ?? {
23827
+ message: "Turn failed",
23828
+ codexErrorInfo: null,
23829
+ additionalDetails: null
23830
+ };
23831
+ this.recordTypedSessionFailure({
23832
+ threadId: this.sessionState.sessionId,
23833
+ turnId: turn.id,
23834
+ willRetry: false,
23835
+ error: error51
23836
+ });
23837
+ }
23625
23838
  takeCompletedPlan() {
23626
23839
  const plan = this.completedPlan;
23627
23840
  this.completedPlan = null;
23628
23841
  return plan;
23629
23842
  }
23630
23843
  async handleNotification(notification) {
23844
+ await this.flushPendingErrors();
23631
23845
  const updateEvent = await this.createUpdateEvent(notification);
23632
23846
  if (updateEvent) {
23633
23847
  await this.session.update(updateEvent);
@@ -23648,6 +23862,14 @@ var CodexEventHandler = class _CodexEventHandler {
23648
23862
  async dispose() {
23649
23863
  if (this.disposed) return;
23650
23864
  await this.flushPendingPlanUpdates();
23865
+ if (this.pendingErrors.length > 0) {
23866
+ logger.log("Discarding app-server errors that arrived before a turn started", {
23867
+ sessionId: this.sessionState.sessionId,
23868
+ count: this.pendingErrors.length,
23869
+ turnIds: this.pendingErrors.map((error51) => error51.turnId)
23870
+ });
23871
+ this.pendingErrors.splice(0);
23872
+ }
23651
23873
  this.disposed = true;
23652
23874
  this.cancelPlanUpdateTimer();
23653
23875
  this.pendingPlanItemIds.clear();
@@ -23657,19 +23879,25 @@ var CodexEventHandler = class _CodexEventHandler {
23657
23879
  async createUpdateEvent(notification) {
23658
23880
  switch (notification.method) {
23659
23881
  case "item/agentMessage/delta":
23882
+ this.completeRetryIncidentOnTurnProgress();
23660
23883
  return await this.createTextEvent(notification.params);
23661
23884
  case "item/plan/delta":
23885
+ this.completeRetryIncidentOnTurnProgress();
23662
23886
  return this.createPlanDeltaEvent(notification.params);
23663
23887
  case "item/started":
23888
+ this.completeRetryIncidentOnTurnProgress();
23664
23889
  return await this.createItemEvent(notification.params);
23665
23890
  case "item/completed":
23891
+ this.completeRetryIncidentOnTurnProgress();
23666
23892
  return await this.completeItemEvent(notification.params);
23667
23893
  case "turn/plan/updated":
23894
+ this.completeRetryIncidentOnTurnProgress();
23668
23895
  return await this.updatePlan(notification.params);
23669
23896
  case "error":
23670
23897
  return await this.createErrorEvent(notification.params);
23671
23898
  case "turn/started":
23672
23899
  this.sessionState.currentTurnId = notification.params.turn.id;
23900
+ await this.flushPendingErrors();
23673
23901
  return null;
23674
23902
  case "turn/completed":
23675
23903
  await this.flushPendingPlanUpdates();
@@ -23702,8 +23930,10 @@ var CodexEventHandler = class _CodexEventHandler {
23702
23930
  closed: true
23703
23931
  });
23704
23932
  case "item/commandExecution/outputDelta":
23933
+ this.completeRetryIncidentOnTurnProgress();
23705
23934
  return this.createCommandOutputDeltaEvent(notification.params);
23706
23935
  case "item/mcpToolCall/progress":
23936
+ this.completeRetryIncidentOnTurnProgress();
23707
23937
  return this.createMcpToolProgressEvent(notification.params);
23708
23938
  case "account/rateLimits/updated":
23709
23939
  this.handleRateLimitsUpdated(notification.params);
@@ -23714,6 +23944,8 @@ var CodexEventHandler = class _CodexEventHandler {
23714
23944
  return this.createWarningEvent(notification.params);
23715
23945
  case "guardianWarning":
23716
23946
  return null;
23947
+ case "deprecationNotice":
23948
+ return this.createDeprecationNoticeEvent(notification.params);
23717
23949
  case "item/autoApprovalReview/started":
23718
23950
  return this.handleGuardianApprovalReviewStarted(notification.params);
23719
23951
  case "item/autoApprovalReview/completed":
@@ -23721,10 +23953,13 @@ var CodexEventHandler = class _CodexEventHandler {
23721
23953
  case "thread/compacted":
23722
23954
  return this.createContextCompactedEvent();
23723
23955
  case "item/reasoning/summaryTextDelta":
23956
+ this.completeRetryIncidentOnTurnProgress();
23724
23957
  return this.createReasoningDeltaEvent(notification.params);
23725
23958
  case "item/reasoning/textDelta":
23959
+ this.completeRetryIncidentOnTurnProgress();
23726
23960
  return this.createReasoningDeltaEvent(notification.params);
23727
23961
  case "item/reasoning/summaryPartAdded":
23962
+ this.completeRetryIncidentOnTurnProgress();
23728
23963
  return this.createReasoningSectionBreakEvent(notification.params);
23729
23964
  case "model/rerouted":
23730
23965
  return this.createModelReroutedEvent(notification.params);
@@ -23767,7 +24002,6 @@ var CodexEventHandler = class _CodexEventHandler {
23767
24002
  case "windowsSandbox/setupCompleted":
23768
24003
  case "account/login/completed":
23769
24004
  case "skills/changed":
23770
- case "deprecationNotice":
23771
24005
  case "mcpServer/oauthLogin/completed":
23772
24006
  case "externalAgentConfig/import/completed":
23773
24007
  case "rawResponseItem/completed":
@@ -23795,14 +24029,31 @@ var CodexEventHandler = class _CodexEventHandler {
23795
24029
  return createAgentTextMessageChunk(event.delta, event.itemId, createCodexMessagePhaseMeta(phase));
23796
24030
  }
23797
24031
  async createConfigWarningEvent(event) {
23798
- const detailsText = event.details ? `
24032
+ if (this.supportsTypedSessionFailures) {
24033
+ return this.createSessionFailureUpdate(this.recordSessionNotice(...this.sessionNoticeContent(event.summary, event.details)));
24034
+ }
24035
+ const text = event.details ? `${event.summary}
23799
24036
 
23800
- ${event.details}` : "";
23801
- return createAgentTextMessageChunk(`Config warning: ${event.summary}${detailsText}
24037
+ ${event.details}` : event.summary;
24038
+ return createAgentTextMessageChunk(`Config warning: ${text}
23802
24039
 
23803
24040
  `);
23804
24041
  }
24042
+ /**
24043
+ * Unlike `warning` and `configWarning`, this notification was dropped outright, so there is no
24044
+ * legacy rendering to preserve. It is surfaced only to clients that negotiated typed records;
24045
+ * every other client keeps seeing exactly what it sees today, which is nothing.
24046
+ */
24047
+ createDeprecationNoticeEvent(event) {
24048
+ if (!this.supportsTypedSessionFailures) return null;
24049
+ return this.createSessionFailureUpdate(
24050
+ this.recordSessionNotice(...this.sessionNoticeContent(event.summary, event.details))
24051
+ );
24052
+ }
23805
24053
  createWarningEvent(event) {
24054
+ if (this.supportsTypedSessionFailures) {
24055
+ return this.createSessionFailureUpdate(this.recordSessionNotice(event.message));
24056
+ }
23806
24057
  return createAgentTextMessageChunk(`Warning: ${event.message}
23807
24058
 
23808
24059
  `);
@@ -23819,9 +24070,7 @@ ${event.details}` : "";
23819
24070
  return null;
23820
24071
  }
23821
24072
  this.sessionState.currentGoal = goalSnapshot;
23822
- return this.createCodexSessionInfoUpdate({
23823
- goal: goalSnapshot
23824
- });
24073
+ return this.createGoalSessionInfoUpdate(goalSnapshot);
23825
24074
  }
23826
24075
  createThreadGoalClearedEvent(_event) {
23827
24076
  this.sessionState.goalRevision += 1;
@@ -23829,9 +24078,13 @@ ${event.details}` : "";
23829
24078
  return null;
23830
24079
  }
23831
24080
  this.sessionState.currentGoal = null;
23832
- return this.createCodexSessionInfoUpdate({
23833
- goal: null
23834
- });
24081
+ return this.createGoalSessionInfoUpdate(null);
24082
+ }
24083
+ createGoalSessionInfoUpdate(goal) {
24084
+ return {
24085
+ sessionUpdate: "session_info_update",
24086
+ _meta: { goal }
24087
+ };
23835
24088
  }
23836
24089
  createReasoningDeltaEvent(event) {
23837
24090
  this.seenReasoningDeltaItemIds.add(event.itemId);
@@ -24167,7 +24420,33 @@ ${event.stdin}
24167
24420
  }
24168
24421
  async createErrorEvent(params) {
24169
24422
  const error51 = params.error.codexErrorInfo;
24423
+ if (this.sessionState.currentTurnId === null) {
24424
+ this.pendingErrors.push(params);
24425
+ logger.log("Buffered app-server error until the active turn is known", {
24426
+ sessionId: this.sessionState.sessionId,
24427
+ turnId: params.turnId,
24428
+ willRetry: params.willRetry
24429
+ });
24430
+ return null;
24431
+ }
24432
+ if (params.turnId !== this.sessionState.currentTurnId) {
24433
+ if (this.supportsTypedSessionFailures) {
24434
+ const failure = params.willRetry ? this.recordRetryWarning(params) : this.recordSessionFailure(
24435
+ this.sessionFailureKind(params.error.codexErrorInfo),
24436
+ params.turnId,
24437
+ "error",
24438
+ params.error.message
24439
+ );
24440
+ return this.createSessionFailureUpdate(failure);
24441
+ }
24442
+ return this.createCodexSessionInfoUpdate({
24443
+ error: { ...params.error, turnId: params.turnId, willRetry: params.willRetry }
24444
+ });
24445
+ }
24170
24446
  if (params.willRetry) {
24447
+ if (this.supportsTypedSessionFailures) {
24448
+ return this.createSessionFailureUpdate(this.recordRetryWarning(params));
24449
+ }
24171
24450
  return this.createCodexSessionInfoUpdate({
24172
24451
  error: {
24173
24452
  ...params.error,
@@ -24175,7 +24454,12 @@ ${event.stdin}
24175
24454
  willRetry: true
24176
24455
  }
24177
24456
  });
24178
- } else if (error51 === "usageLimitExceeded") {
24457
+ }
24458
+ if (this.supportsTypedSessionFailures) {
24459
+ this.recordTypedSessionFailure(params);
24460
+ return null;
24461
+ }
24462
+ if (error51 === "usageLimitExceeded") {
24179
24463
  this.failure = RequestError.internalError(
24180
24464
  this.createTurnErrorData(params.error)
24181
24465
  );
@@ -24186,22 +24470,125 @@ ${event.stdin}
24186
24470
 
24187
24471
  `);
24188
24472
  }
24473
+ recordTypedSessionFailure(params) {
24474
+ const kind = this.sessionFailureKind(params.error.codexErrorInfo);
24475
+ this.recordSessionFailure(kind, params.turnId, "error", params.error.message);
24476
+ }
24477
+ recordSessionFailure(kind, turnId, severity, title, actionsOverride, attributeToTurn = true) {
24478
+ const policy = SESSION_FAILURE_POLICY[kind];
24479
+ const scope = turnId ?? this.sessionState.sessionId;
24480
+ const id = this.activeFailureIdByScope.get(scope) ?? this.allocateFailureId(scope, turnId);
24481
+ const previous = this.failuresById.get(id);
24482
+ const failure = {
24483
+ id,
24484
+ revision: nextSessionFailureRevision(previous, id),
24485
+ category: policy.category,
24486
+ severity,
24487
+ title,
24488
+ actions: actionsOverride ?? policy.actions
24489
+ };
24490
+ this.failuresById.set(id, failure);
24491
+ this.failureTurnIdById.set(id, attributeToTurn ? turnId : void 0);
24492
+ this.activeFailureIdByScope.set(scope, id);
24493
+ this.sessionState.sessionFailure = failure;
24494
+ this.lastSessionNotice = void 0;
24495
+ return failure;
24496
+ }
24497
+ allocateFailureId(scope, turnId) {
24498
+ if (turnId !== void 0 && !this.allocatedFailureScopes.has(scope)) {
24499
+ this.allocatedFailureScopes.add(scope);
24500
+ return `${turnId}:error`;
24501
+ }
24502
+ this.allocatedFailureScopes.add(scope);
24503
+ return `${scope}:error:${this.sessionFailureEpoch}:${this.nextNoticeId++}`;
24504
+ }
24505
+ /**
24506
+ * A retry warning remains the active incident until Codex produces turn content again. That content is
24507
+ * the only positive signal available from app-server that the turn recovered; a later error then starts
24508
+ * a new incident instead of overwriting the historical reconnect entry. Terminal errors remain active so
24509
+ * duplicate late notifications cannot append duplicate transcript rows.
24510
+ */
24511
+ completeRetryIncidentOnTurnProgress() {
24512
+ const turnId = this.sessionState.currentTurnId;
24513
+ if (turnId === null) return;
24514
+ const activeId = this.activeFailureIdByScope.get(turnId);
24515
+ if (activeId === void 0 || this.failuresById.get(activeId)?.severity !== "warning") return;
24516
+ this.activeFailureIdByScope.delete(turnId);
24517
+ if (this.sessionState.sessionFailure?.id === activeId) {
24518
+ delete this.sessionState.sessionFailure;
24519
+ }
24520
+ }
24521
+ recordRetryWarning(params, attributeToTurn = true) {
24522
+ const kind = this.sessionFailureKind(params.error.codexErrorInfo);
24523
+ return this.recordSessionFailure(
24524
+ kind,
24525
+ params.turnId,
24526
+ "warning",
24527
+ params.error.message,
24528
+ [],
24529
+ attributeToTurn
24530
+ );
24531
+ }
24532
+ recordSessionNotice(title, details) {
24533
+ const key = `${title}\0${details ?? ""}`;
24534
+ const previous = this.lastSessionNotice?.key === key ? this.lastSessionNotice.failure : void 0;
24535
+ const id = previous?.id ?? `${this.sessionState.sessionId}:notice:${this.sessionFailureEpoch}:${this.nextNoticeId++}`;
24536
+ const notice = {
24537
+ id,
24538
+ revision: nextSessionFailureRevision(previous, id),
24539
+ category: "unknown",
24540
+ severity: "warning",
24541
+ title,
24542
+ ...details === void 0 ? {} : { details },
24543
+ actions: []
24544
+ };
24545
+ this.lastSessionNotice = { key, failure: notice };
24546
+ return notice;
24547
+ }
24548
+ sessionNoticeContent(summary, details) {
24549
+ if (details === null) return [summary];
24550
+ const combinedTitle = `${summary} \u2014 ${details}`;
24551
+ return combinedTitle.length <= MAX_SESSION_FAILURE_TITLE_LENGTH ? [combinedTitle] : [summary, details];
24552
+ }
24553
+ createSessionFailureMeta(failure) {
24554
+ return {
24555
+ [JETBRAINS_META_KEY]: {
24556
+ [AIR_META_KEY]: {
24557
+ [AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
24558
+ [AIR_SESSION_FAILURE_KEY]: failure
24559
+ }
24560
+ }
24561
+ };
24562
+ }
24563
+ createSessionFailureUpdate(failure) {
24564
+ return {
24565
+ sessionUpdate: "session_info_update",
24566
+ _meta: this.createSessionFailureMeta(failure)
24567
+ };
24568
+ }
24569
+ sessionFailureKind(error51) {
24570
+ if (this.isAuthenticationRequiredError(error51)) return "auth_required";
24571
+ if (this.getHttpStatusCode(error51) === 429) return "rate_limited";
24572
+ if (typeof error51 === "string") {
24573
+ return STRING_CODEX_ERROR_CATEGORIES[error51] ?? "provider_error";
24574
+ }
24575
+ if (error51 !== null) {
24576
+ for (const kind of Object.keys(STRUCTURED_CODEX_ERROR_CATEGORIES)) {
24577
+ if (kind in error51) {
24578
+ return STRUCTURED_CODEX_ERROR_CATEGORIES[kind] ?? "provider_error";
24579
+ }
24580
+ }
24581
+ }
24582
+ return "provider_error";
24583
+ }
24189
24584
  isAuthenticationRequiredError(error51) {
24190
24585
  return error51 === "unauthorized" || this.getHttpStatusCode(error51) === 401;
24191
24586
  }
24192
24587
  getHttpStatusCode(error51) {
24193
- if (error51 !== null && typeof error51 === "object") {
24194
- if ("httpConnectionFailed" in error51) {
24195
- return error51.httpConnectionFailed.httpStatusCode;
24196
- } else if ("responseStreamConnectionFailed" in error51) {
24197
- return error51.responseStreamConnectionFailed.httpStatusCode;
24198
- } else if ("responseStreamDisconnected" in error51) {
24199
- return error51.responseStreamDisconnected.httpStatusCode;
24200
- } else if ("responseTooManyFailedAttempts" in error51) {
24201
- return error51.responseTooManyFailedAttempts.httpStatusCode;
24202
- }
24203
- }
24204
- return null;
24588
+ if (error51 === null || typeof error51 !== "object") return null;
24589
+ const details = Object.values(error51)[0];
24590
+ if (details === null || typeof details !== "object" || !("httpStatusCode" in details)) return null;
24591
+ return typeof details.httpStatusCode === "number" ? details.httpStatusCode : null;
24205
24592
  }
24206
24593
  createTurnErrorData(error51) {
24207
24594
  const data = {
@@ -24630,11 +25017,11 @@ var CodexApprovalHandler = class {
24630
25017
  });
24631
25018
  }
24632
25019
  const fileSystem = permissions.fileSystem;
24633
- for (const path6 of fileSystem?.read ?? []) {
24634
- changes.push(this.fileSystemGrantChange(path6, "read", lifetime, suffix));
25020
+ for (const path7 of fileSystem?.read ?? []) {
25021
+ changes.push(this.fileSystemGrantChange(path7, "read", lifetime, suffix));
24635
25022
  }
24636
- for (const path6 of fileSystem?.write ?? []) {
24637
- changes.push(this.fileSystemGrantChange(path6, "write", lifetime, suffix));
25023
+ for (const path7 of fileSystem?.write ?? []) {
25024
+ changes.push(this.fileSystemGrantChange(path7, "write", lifetime, suffix));
24638
25025
  }
24639
25026
  for (const entry of fileSystem?.entries ?? []) {
24640
25027
  const matcher = (() => {
@@ -24663,16 +25050,16 @@ var CodexApprovalHandler = class {
24663
25050
  }
24664
25051
  return changes.length > 0 ? { version: 1, changes } : void 0;
24665
25052
  }
24666
- fileSystemGrantChange(path6, access, lifetime, suffix) {
25053
+ fileSystemGrantChange(path7, access, lifetime, suffix) {
24667
25054
  return {
24668
25055
  type: "grant",
24669
25056
  operation: "grant",
24670
- description: `Allow ${access} access to ${path6}${suffix}`,
25057
+ description: `Allow ${access} access to ${path7}${suffix}`,
24671
25058
  lifetime,
24672
25059
  targets: [{
24673
25060
  type: "filesystem",
24674
25061
  access: [access],
24675
- matcher: { type: "exact_path", path: path6 }
25062
+ matcher: { type: "exact_path", path: path7 }
24676
25063
  }]
24677
25064
  };
24678
25065
  }
@@ -25360,6 +25747,11 @@ var ChatGptAuthMethod = {
25360
25747
  name: "ChatGPT",
25361
25748
  description: "Use ChatGPT to authenticate"
25362
25749
  };
25750
+ var ChatGptDeviceCodeAuthMethod = {
25751
+ id: "chat-gpt-device-code",
25752
+ name: "ChatGPT (device code)",
25753
+ description: "Sign in to ChatGPT by opening a verification page and entering a one-time code"
25754
+ };
25363
25755
  var GatewayAuthMethod = {
25364
25756
  id: "gateway",
25365
25757
  name: "Custom model gateway",
@@ -25376,6 +25768,9 @@ function getCodexAuthMethods(clientCapabilities, env = process.env) {
25376
25768
  if (!env["NO_BROWSER"]) {
25377
25769
  authMethods.push(ChatGptAuthMethod);
25378
25770
  }
25771
+ if (clientSupportsUrlElicitation(clientCapabilities)) {
25772
+ authMethods.push(ChatGptDeviceCodeAuthMethod);
25773
+ }
25379
25774
  const supportsGatewayAuth = clientCapabilities?.auth?._meta?.["gateway"] === true;
25380
25775
  if (supportsGatewayAuth) {
25381
25776
  authMethods.push(GatewayAuthMethod);
@@ -25383,7 +25778,7 @@ function getCodexAuthMethods(clientCapabilities, env = process.env) {
25383
25778
  return authMethods;
25384
25779
  }
25385
25780
  function isCodexAuthRequest(request) {
25386
- return request.methodId === "api-key" || request.methodId === "chat-gpt" || request.methodId === "gateway";
25781
+ return request.methodId === "api-key" || request.methodId === "chat-gpt" || request.methodId === "chat-gpt-device-code" || request.methodId === "gateway";
25387
25782
  }
25388
25783
 
25389
25784
  // node_modules/open/index.js
@@ -25574,15 +25969,15 @@ var wslDefaultBrowser = async () => {
25574
25969
  const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
25575
25970
  return stdout.trim();
25576
25971
  };
25577
- var convertWslPathToWindows = async (path6) => {
25578
- if (/^[a-z]+:\/\//i.test(path6)) {
25579
- return path6;
25972
+ var convertWslPathToWindows = async (path7) => {
25973
+ if (/^[a-z]+:\/\//i.test(path7)) {
25974
+ return path7;
25580
25975
  }
25581
25976
  try {
25582
- const { stdout } = await execFile2("wslpath", ["-aw", path6], { encoding: "utf8" });
25977
+ const { stdout } = await execFile2("wslpath", ["-aw", path7], { encoding: "utf8" });
25583
25978
  return stdout.trim();
25584
25979
  } catch {
25585
- return path6;
25980
+ return path7;
25586
25981
  }
25587
25982
  };
25588
25983
 
@@ -26132,7 +26527,7 @@ var AgentMode = class _AgentMode {
26132
26527
  };
26133
26528
 
26134
26529
  // src/CodexAcpClient.ts
26135
- import path4 from "node:path";
26530
+ import path5 from "node:path";
26136
26531
 
26137
26532
  // src/McpServerName.ts
26138
26533
  var MCP_SERVER_NAME_WHITESPACE = /\p{White_Space}/gu;
@@ -26146,7 +26541,7 @@ var package_default = {
26146
26541
  publishConfig: {
26147
26542
  access: "public"
26148
26543
  },
26149
- version: "1.1.9-agentconnect.1",
26544
+ version: "1.3.0-agentconnect.1",
26150
26545
  description: "",
26151
26546
  main: "dist/index.js",
26152
26547
  bin: {
@@ -26178,6 +26573,7 @@ var package_default = {
26178
26573
  "example:steering": "node --import tsx examples/steering.ts",
26179
26574
  "example:steering:multistep": "node --import tsx examples/steering.ts",
26180
26575
  "generate-types": "./node_modules/.bin/codex app-server generate-ts --out src/app-server",
26576
+ "release:preflight": "bash scripts/release-preflight.sh",
26181
26577
  test: "vitest run",
26182
26578
  "test:e2e": "npm run build && RUN_E2E_TESTS=true vitest run src/__tests__/CodexACPAgent/e2e",
26183
26579
  "test:watch": "vitest",
@@ -26206,7 +26602,7 @@ var package_default = {
26206
26602
  },
26207
26603
  dependencies: {
26208
26604
  "@agentclientprotocol/sdk": "^1.3.0",
26209
- "@openai/codex": "^0.145.0",
26605
+ "@openai/codex": "^0.147.0",
26210
26606
  diff: "^9.0.0",
26211
26607
  open: "^11.0.0",
26212
26608
  "vscode-jsonrpc": "^9.0.1",
@@ -26249,6 +26645,54 @@ function createCodexCollaborationMode(mode, currentModelId) {
26249
26645
  };
26250
26646
  }
26251
26647
 
26648
+ // src/PathUtils.ts
26649
+ import path4 from "node:path";
26650
+ function isAbsolutePathLike(value) {
26651
+ const trimmed = value.trim();
26652
+ return path4.isAbsolute(trimmed) || isWindowsAbsolutePath(trimmed);
26653
+ }
26654
+ function arePathsEqual(left, right) {
26655
+ return normalizePathForComparison(left) === normalizePathForComparison(right);
26656
+ }
26657
+ function arePathBasenamesEqual(left, right) {
26658
+ const leftBase = path4.posix.basename(normalizePathForComparison(left));
26659
+ const rightBase = path4.posix.basename(normalizePathForComparison(right));
26660
+ if (shouldComparePathCaseInsensitive(left) || shouldComparePathCaseInsensitive(right)) {
26661
+ return leftBase.toLowerCase() === rightBase.toLowerCase();
26662
+ }
26663
+ return leftBase === rightBase;
26664
+ }
26665
+ function normalizePathForComparison(value) {
26666
+ const trimmed = value.trim();
26667
+ if (trimmed.length === 0) {
26668
+ return "";
26669
+ }
26670
+ if (isWindowsAbsolutePath(trimmed)) {
26671
+ const normalized2 = path4.win32.normalize(trimmed).replace(/\\/g, "/");
26672
+ return trimTrailingPathSeparators(normalized2).toLowerCase();
26673
+ }
26674
+ const pathForComparison = path4.isAbsolute(trimmed) ? trimmed : trimmed.replace(/\\/g, "/");
26675
+ const normalized = path4.posix.normalize(pathForComparison);
26676
+ return trimTrailingPathSeparators(normalized);
26677
+ }
26678
+ function isWindowsAbsolutePath(value) {
26679
+ const portableValue = value.replace(/\\/g, "/");
26680
+ return /^[A-Za-z]:\//.test(portableValue) || /^\/\/[^/]+\/[^/]+/.test(portableValue);
26681
+ }
26682
+ function shouldComparePathCaseInsensitive(value) {
26683
+ return isWindowsAbsolutePath(value) || /^[A-Za-z]:/.test(value) || value.includes("\\");
26684
+ }
26685
+ function trimTrailingPathSeparators(value) {
26686
+ let trimmed = value;
26687
+ while (trimmed.endsWith("/") && !isRootPath(trimmed)) {
26688
+ trimmed = trimmed.slice(0, -1);
26689
+ }
26690
+ return trimmed;
26691
+ }
26692
+ function isRootPath(value) {
26693
+ return value === "/" || /^[A-Za-z]:\/$/.test(value) || /^\/\/[^/]+\/[^/]+\/$/.test(value);
26694
+ }
26695
+
26252
26696
  // src/ApprovalsReviewerConfig.ts
26253
26697
  var APPROVALS_REVIEWER_CONFIG_ID = "approvals_reviewer";
26254
26698
  var USER_APPROVALS_REVIEWER = "user";
@@ -26313,6 +26757,8 @@ function permissionProfileForMode(config2, modeId) {
26313
26757
 
26314
26758
  // src/CodexAcpClient.ts
26315
26759
  var CUSTOM_GATEWAY_PROVIDER_ID = "custom-gateway";
26760
+ var OPENAI_PROVIDER_ID = "openai";
26761
+ var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
26316
26762
  var SUPPORTED_GATEWAY_PROTOCOLS = {
26317
26763
  openai: "responses"
26318
26764
  };
@@ -26356,43 +26802,24 @@ var CodexAcpClient = class {
26356
26802
  getHomePath() {
26357
26803
  return this.configPath;
26358
26804
  }
26359
- async authenticate(authRequest) {
26805
+ async authenticate(authRequest, urlElicitationRequester) {
26360
26806
  if (!isCodexAuthRequest(authRequest)) {
26361
26807
  throw RequestError.invalidRequest();
26362
26808
  }
26363
26809
  this.gatewayConfig = null;
26364
26810
  switch (authRequest.methodId) {
26365
- case "api-key": {
26366
- const apiKey = authRequest._meta?.["api-key"]?.apiKey ?? this.readApiKeyFromEnv();
26367
- return await this.authenticateWithApiKey(apiKey);
26368
- }
26369
- case "chat-gpt": {
26370
- const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
26371
- if (accountResponse.account?.type === "chatgpt") {
26372
- return true;
26373
- }
26374
- const loginCompletedPromise = this.awaitNextLoginCompleted();
26375
- const loginResponse = await this.codexClient.accountLogin({ type: "chatgpt" });
26376
- if (loginResponse.type == "chatgpt") {
26377
- await open_default(loginResponse.authUrl);
26378
- }
26379
- const result = await loginCompletedPromise;
26380
- return result.success;
26381
- }
26811
+ case "api-key":
26812
+ return await this.authenticateWithApiKey(authRequest);
26813
+ case "chat-gpt":
26814
+ return await this.authenticateWithChatGpt();
26815
+ case "chat-gpt-device-code":
26816
+ return await this.authenticateWithChatGptDeviceCode(urlElicitationRequester);
26382
26817
  case "gateway":
26383
- if (!authRequest._meta) throw RequestError.invalidRequest();
26384
- const gatewaySettings = authRequest._meta["gateway"];
26385
- if (!gatewaySettings) throw RequestError.invalidRequest();
26386
- this.applyGatewayConfig({
26387
- baseUrl: gatewaySettings.baseUrl,
26388
- apiType: GatewayAuthMethod._meta.gateway.protocol,
26389
- headers: gatewaySettings.headers,
26390
- providerName: gatewaySettings.providerName
26391
- });
26392
- return true;
26818
+ return this.authenticateWithGateway(authRequest);
26393
26819
  }
26394
26820
  }
26395
- async authenticateWithApiKey(apiKey) {
26821
+ async authenticateWithApiKey(authRequest) {
26822
+ const apiKey = authRequest._meta?.["api-key"]?.apiKey ?? this.readApiKeyFromEnv();
26396
26823
  const loginCompletedPromise = this.awaitNextLoginCompleted();
26397
26824
  await this.codexClient.accountLogin({
26398
26825
  type: "apiKey",
@@ -26401,6 +26828,56 @@ var CodexAcpClient = class {
26401
26828
  const result = await loginCompletedPromise;
26402
26829
  return result.success;
26403
26830
  }
26831
+ async authenticateWithChatGpt() {
26832
+ const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
26833
+ if (accountResponse.account?.type === "chatgpt") {
26834
+ return true;
26835
+ }
26836
+ const loginCompletedPromise = this.awaitNextLoginCompleted();
26837
+ const loginResponse = await this.codexClient.accountLogin({ type: "chatgpt" });
26838
+ if (loginResponse.type == "chatgpt") {
26839
+ await open_default(loginResponse.authUrl);
26840
+ }
26841
+ const result = await loginCompletedPromise;
26842
+ return result.success;
26843
+ }
26844
+ async authenticateWithChatGptDeviceCode(urlElicitationRequester) {
26845
+ const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
26846
+ if (accountResponse.account?.type === "chatgpt") {
26847
+ return true;
26848
+ }
26849
+ if (!urlElicitationRequester) {
26850
+ throw RequestError.invalidRequest(void 0, "Device code authentication requires URL elicitation support");
26851
+ }
26852
+ const loginCompletedPromise = this.awaitNextLoginCompleted();
26853
+ const loginResponse = await this.codexClient.accountLogin({ type: "chatgptDeviceCode" });
26854
+ if (loginResponse.type !== "chatgptDeviceCode") {
26855
+ return false;
26856
+ }
26857
+ const elicitationResponse = await urlElicitationRequester.elicitUrl({
26858
+ url: loginResponse.verificationUrl,
26859
+ message: `Sign in to ChatGPT and enter this code: ${loginResponse.userCode}`,
26860
+ elicitationId: loginResponse.loginId
26861
+ });
26862
+ if (!CreateElicitationResponse.isAccept(elicitationResponse)) {
26863
+ await this.codexClient.accountLoginCancel({ loginId: loginResponse.loginId });
26864
+ return false;
26865
+ }
26866
+ const result = await loginCompletedPromise;
26867
+ return result.success;
26868
+ }
26869
+ authenticateWithGateway(authRequest) {
26870
+ if (!authRequest._meta) throw RequestError.invalidRequest();
26871
+ const gatewaySettings = authRequest._meta["gateway"];
26872
+ if (!gatewaySettings) throw RequestError.invalidRequest();
26873
+ this.applyGatewayConfig({
26874
+ baseUrl: gatewaySettings.baseUrl,
26875
+ apiType: GatewayAuthMethod._meta.gateway.protocol,
26876
+ headers: gatewaySettings.headers,
26877
+ providerName: gatewaySettings.providerName
26878
+ });
26879
+ return true;
26880
+ }
26404
26881
  readApiKeyFromEnv() {
26405
26882
  for (const envVar of [CODEX_API_KEY_ENV_VAR, OPENAI_API_KEY_ENV_VAR]) {
26406
26883
  const value = process.env[envVar]?.trim();
@@ -26497,34 +26974,47 @@ var CodexAcpClient = class {
26497
26974
  };
26498
26975
  }
26499
26976
  /**
26500
- * `providers/list`: returns the single client-configurable custom gateway
26501
- * provider. `current` carries only non-secret routing (never headers), and is
26502
- * `null` when the provider is not configured/disabled.
26977
+ * `providers/list`: returns Codex's OpenAI slot. With no ACP override, the
26978
+ * slot reports native OpenAI routing; headers are never exposed.
26503
26979
  */
26504
26980
  listProviders() {
26505
26981
  const gatewayConfig = this.gatewayConfig;
26506
26982
  const current = gatewayConfig ? {
26507
26983
  apiType: gatewayApiTypeFromConfig(gatewayConfig),
26508
26984
  baseUrl: gatewayConfig.config.base_url
26509
- } : null;
26985
+ } : this.getNativeProviderConfig();
26510
26986
  return [
26511
26987
  {
26512
- providerId: CUSTOM_GATEWAY_PROVIDER_ID,
26988
+ providerId: OPENAI_PROVIDER_ID,
26513
26989
  supported: Object.keys(SUPPORTED_GATEWAY_PROTOCOLS),
26514
26990
  required: false,
26515
26991
  current
26516
26992
  }
26517
26993
  ];
26518
26994
  }
26995
+ getNativeProviderConfig() {
26996
+ const configuredProviderId = this.modelProvider ?? (typeof this.config["model_provider"] === "string" ? this.config["model_provider"] : null);
26997
+ const configuredProviders = this.config["model_providers"];
26998
+ if (configuredProviderId && configuredProviders && typeof configuredProviders === "object" && !Array.isArray(configuredProviders)) {
26999
+ const configuredProvider = configuredProviders[configuredProviderId];
27000
+ if (configuredProvider && typeof configuredProvider === "object" && !Array.isArray(configuredProvider)) {
27001
+ const baseUrl = configuredProvider["base_url"];
27002
+ if (typeof baseUrl === "string" && baseUrl.length > 0) {
27003
+ return { apiType: "openai", baseUrl };
27004
+ }
27005
+ }
27006
+ }
27007
+ return { apiType: "openai", baseUrl: DEFAULT_OPENAI_BASE_URL };
27008
+ }
26519
27009
  /**
26520
27010
  * `providers/set`: replaces the full configuration for the custom gateway
26521
27011
  * provider. Rejects unknown provider ids with `invalid_params`.
26522
27012
  */
26523
27013
  setProvider(request) {
26524
- if (request.providerId !== CUSTOM_GATEWAY_PROVIDER_ID) {
27014
+ if (request.providerId !== OPENAI_PROVIDER_ID) {
26525
27015
  throw RequestError.invalidParams(
26526
27016
  { providerId: request.providerId },
26527
- `Unknown providerId "${request.providerId}"; only "${CUSTOM_GATEWAY_PROVIDER_ID}" is configurable`
27017
+ `Unknown providerId "${request.providerId}"; only "${OPENAI_PROVIDER_ID}" is configurable`
26528
27018
  );
26529
27019
  }
26530
27020
  this.applyGatewayConfig({
@@ -26538,7 +27028,7 @@ var CodexAcpClient = class {
26538
27028
  * unknown provider id is idempotent success (RFD behavior §7).
26539
27029
  */
26540
27030
  disableProvider(request) {
26541
- if (request.providerId === CUSTOM_GATEWAY_PROVIDER_ID) {
27031
+ if (request.providerId === OPENAI_PROVIDER_ID) {
26542
27032
  this.gatewayConfig = null;
26543
27033
  }
26544
27034
  }
@@ -26659,12 +27149,16 @@ var CodexAcpClient = class {
26659
27149
  const response = await this.codexClient.threadGoalGet({ threadId: sessionId });
26660
27150
  return response?.goal ?? null;
26661
27151
  }
26662
- async setGoal(sessionId, objective, onTurnStarted) {
26663
- return await this.codexClient.runGoalSet({
27152
+ async setGoal(sessionId, objective, onTurnStarted, onGoalSet) {
27153
+ const params = {
26664
27154
  threadId: sessionId,
26665
27155
  objective,
26666
27156
  status: "active"
26667
- }, onTurnStarted);
27157
+ };
27158
+ if (onGoalSet === void 0) {
27159
+ return await this.codexClient.runGoalSet(params, onTurnStarted);
27160
+ }
27161
+ return await this.codexClient.runGoalSet(params, onTurnStarted, void 0, onGoalSet);
26668
27162
  }
26669
27163
  async setGoalStatus(sessionId, status) {
26670
27164
  let updatedGoal = null;
@@ -26679,11 +27173,15 @@ var CodexAcpClient = class {
26679
27173
  }
26680
27174
  return updatedGoal;
26681
27175
  }
26682
- async resumeGoal(sessionId, onTurnStarted) {
26683
- return await this.codexClient.runGoalSet({
27176
+ async resumeGoal(sessionId, onTurnStarted, onGoalSet) {
27177
+ const params = {
26684
27178
  threadId: sessionId,
26685
27179
  status: "active"
26686
- }, onTurnStarted);
27180
+ };
27181
+ if (onGoalSet === void 0) {
27182
+ return await this.codexClient.runGoalSet(params, onTurnStarted);
27183
+ }
27184
+ return await this.codexClient.runGoalSet(params, onTurnStarted, void 0, onGoalSet);
26687
27185
  }
26688
27186
  async clearGoal(sessionId) {
26689
27187
  await this.codexClient.runGoalClear({ threadId: sessionId });
@@ -26746,7 +27244,7 @@ var CodexAcpClient = class {
26746
27244
  if (!cwd) {
26747
27245
  return;
26748
27246
  }
26749
- const skillExtraRoots = additionalRoots.map((root) => path4.join(root, ".agents", "skills"));
27247
+ const skillExtraRoots = additionalRoots.map((root) => path5.join(root, ".agents", "skills"));
26750
27248
  if (!arraysEqual(this.skillExtraRoots, skillExtraRoots)) {
26751
27249
  await this.codexClient.skillsExtraRootsSet({ extraRoots: skillExtraRoots });
26752
27250
  this.skillExtraRoots = skillExtraRoots;
@@ -26952,11 +27450,10 @@ var CodexAcpClient = class {
26952
27450
  const requestedCwd = request.cwd?.trim() ?? null;
26953
27451
  const filterByCwd = (thread) => {
26954
27452
  if (!requestedCwd) return true;
26955
- if (path4.isAbsolute(requestedCwd)) {
26956
- return thread.cwd === requestedCwd;
27453
+ if (isAbsolutePathLike(requestedCwd)) {
27454
+ return arePathsEqual(thread.cwd, requestedCwd);
26957
27455
  }
26958
- const requestedBase = path4.basename(requestedCwd);
26959
- return path4.basename(thread.cwd) === requestedBase;
27456
+ return arePathBasenamesEqual(thread.cwd, requestedCwd);
26960
27457
  };
26961
27458
  const preferredProvider = this.getModelProvider();
26962
27459
  const modelProviders = preferredProvider ? [preferredProvider] : [];
@@ -26978,7 +27475,7 @@ var CodexAcpClient = class {
26978
27475
  let sessions = listResponse.data.map(mapThreadToSession);
26979
27476
  if (requestedCwd) {
26980
27477
  const filtered = listResponse.data.filter(filterByCwd).map(mapThreadToSession);
26981
- if (filtered.length > 0 || path4.isAbsolute(requestedCwd)) {
27478
+ if (filtered.length > 0 || isAbsolutePathLike(requestedCwd)) {
26982
27479
  sessions = filtered;
26983
27480
  } else {
26984
27481
  logger.log("Ignoring non-absolute cwd filter for session/list", { cwd: requestedCwd });
@@ -27093,8 +27590,8 @@ function formatUriAsLink(name, uri) {
27093
27590
  return `[@${name}](${uri})`;
27094
27591
  }
27095
27592
  if (uri.startsWith("file://")) {
27096
- const path6 = uri.replace("file://", "");
27097
- const fileName = path6.split("/").pop() ?? path6;
27593
+ const path7 = uri.replace("file://", "");
27594
+ const fileName = path7.split("/").pop() ?? path7;
27098
27595
  return `[@${fileName}](${uri})`;
27099
27596
  }
27100
27597
  return uri;
@@ -27124,7 +27621,7 @@ function readAdditionalDirectories(cwd, additionalDirectories, meta3) {
27124
27621
  if (directory.length === 0) {
27125
27622
  throw RequestError.invalidParams(void 0, "additionalDirectories entries must not be empty");
27126
27623
  }
27127
- if (!path4.isAbsolute(directory)) {
27624
+ if (!path5.isAbsolute(directory)) {
27128
27625
  throw RequestError.invalidParams(void 0, "additionalDirectories entries must be absolute paths");
27129
27626
  }
27130
27627
  if (!seen.has(directory)) {
@@ -27242,6 +27739,10 @@ function createReasoningEffortConfigOption(supportedReasoningEfforts, currentEff
27242
27739
  }
27243
27740
 
27244
27741
  // src/CodexCommands.ts
27742
+ var GOAL_CONTINUATION_PROMPT = [{
27743
+ type: "text",
27744
+ text: "Continue working toward the active goal."
27745
+ }];
27245
27746
  var CodexCommands = class {
27246
27747
  connection;
27247
27748
  codexAcpClient;
@@ -27530,7 +28031,7 @@ var CodexCommands = class {
27530
28031
  }
27531
28032
  createGoalCommandResult(turnCompleted) {
27532
28033
  if (turnCompleted === null) {
27533
- return { handled: true };
28034
+ return { handled: false, prompt: GOAL_CONTINUATION_PROMPT };
27534
28035
  }
27535
28036
  return {
27536
28037
  handled: true,
@@ -27726,7 +28227,7 @@ var SteeringQueue = class {
27726
28227
 
27727
28228
  // src/ResponseItemHistoryFallback.ts
27728
28229
  import { readFile as readFile2 } from "node:fs/promises";
27729
- import path5 from "node:path";
28230
+ import path6 from "node:path";
27730
28231
  function historyFallbackUpdateKey(update) {
27731
28232
  switch (update.sessionUpdate) {
27732
28233
  case "user_message_chunk":
@@ -27966,8 +28467,8 @@ function imageBlocks(images) {
27966
28467
  return [{ type: "text", text: `[@image](${image})` }];
27967
28468
  }
27968
28469
  const record2 = asRecord(image);
27969
- const path6 = record2 ? stringValue(record2["path"]) ?? stringValue(record2["url"]) : null;
27970
- return path6 ? [{ type: "text", text: `[@image](${path6})` }] : [];
28470
+ const path7 = record2 ? stringValue(record2["path"]) ?? stringValue(record2["url"]) : null;
28471
+ return path7 ? [{ type: "text", text: `[@image](${path7})` }] : [];
27971
28472
  });
27972
28473
  }
27973
28474
  function contentBlocksFromResponseContent(content) {
@@ -28599,10 +29100,10 @@ function baseCommandName(commandName) {
28599
29100
  return commandName.split(/[\\/]/).pop() ?? commandName;
28600
29101
  }
28601
29102
  function absolutizePath(cwd, targetPath) {
28602
- if (path5.isAbsolute(targetPath) || cwd.length === 0) {
29103
+ if (path6.isAbsolute(targetPath) || cwd.length === 0) {
28603
29104
  return targetPath;
28604
29105
  }
28605
- return path5.join(cwd, targetPath);
29106
+ return path6.join(cwd, targetPath);
28606
29107
  }
28607
29108
  function withTerminalContent(event, terminalId, cwd) {
28608
29109
  const { rawInput, ...eventWithoutRawInput } = event;
@@ -28686,6 +29187,13 @@ function numberValue(value) {
28686
29187
  return typeof value === "number" && Number.isFinite(value) ? value : null;
28687
29188
  }
28688
29189
 
29190
+ // src/AcpExtensions.ts
29191
+ var LEGACY_SET_SESSION_MODEL_METHOD = "session/set_model";
29192
+ var SESSION_STEERING_METHOD = "_session/steering";
29193
+ function isExtMethodRequest(request) {
29194
+ return request.method === "authentication/status" || request.method === "authentication/logout" || request.method === LEGACY_SET_SESSION_MODEL_METHOD || request.method === GOAL_CONTROL_METHOD || request.method === LEGACY_GOAL_CONTROL_METHOD || request.method === SESSION_STEERING_METHOD;
29195
+ }
29196
+
28689
29197
  // src/FastModeConfig.ts
28690
29198
  var FAST_MODE_CONFIG_ID = "fast-mode";
28691
29199
  var FAST_MODE_CATEGORY = "model_config";
@@ -28751,8 +29259,17 @@ function clientSupportsPlanUpdates(clientCapabilities) {
28751
29259
  }
28752
29260
 
28753
29261
  // src/CodexAcpServer.ts
29262
+ import { randomUUID as randomUUID2 } from "node:crypto";
28754
29263
  var IMPLEMENT_PLAN_OPTION_ID = "implement_plan";
28755
29264
  var REVISE_PLAN_OPTION_ID = "revise_plan";
29265
+ var CODEX_PROCESS_EXITED_ERROR_CODE = 1001;
29266
+ function clientSupportsTypedSessionFailures(capabilities) {
29267
+ const jetbrains = capabilities?._meta?.[JETBRAINS_META_KEY];
29268
+ const air = jetbrains?.[AIR_META_KEY];
29269
+ const version2 = air?.[AIR_EXTENSION_VERSION_KEY];
29270
+ const supported = air?.[AIR_EXTENSION_CAPABILITIES_KEY];
29271
+ return typeof version2 === "number" && Number.isInteger(version2) && version2 >= AIR_EXTENSION_VERSION && Array.isArray(supported) && supported.includes(AIR_SESSION_FAILURE_KEY);
29272
+ }
28756
29273
  var CodexAcpServer = class _CodexAcpServer {
28757
29274
  static MODEL_NAME_TOKEN_OVERRIDES = {
28758
29275
  gpt: "GPT",
@@ -28764,6 +29281,7 @@ var CodexAcpServer = class _CodexAcpServer {
28764
29281
  defaultAuthRequest;
28765
29282
  getExitCode;
28766
29283
  getRecentStderr;
29284
+ sessionFailureEpoch;
28767
29285
  availableCommands;
28768
29286
  clientInfo;
28769
29287
  clientCapabilities;
@@ -28777,6 +29295,7 @@ var CodexAcpServer = class _CodexAcpServer {
28777
29295
  closingSessions;
28778
29296
  sessionGenerations;
28779
29297
  sessionOpenGenerations;
29298
+ goalControlGenerations;
28780
29299
  constructor(connection, codexAcpClient, defaultAuthRequest, getExitCode, getRecentStderr) {
28781
29300
  this.sessions = /* @__PURE__ */ new Map();
28782
29301
  this.pendingMcpStartupSessions = /* @__PURE__ */ new Map();
@@ -28786,11 +29305,13 @@ var CodexAcpServer = class _CodexAcpServer {
28786
29305
  this.closingSessions = /* @__PURE__ */ new Map();
28787
29306
  this.sessionGenerations = /* @__PURE__ */ new Map();
28788
29307
  this.sessionOpenGenerations = /* @__PURE__ */ new Map();
29308
+ this.goalControlGenerations = /* @__PURE__ */ new Map();
28789
29309
  this.connection = connection;
28790
29310
  this.codexAcpClient = codexAcpClient;
28791
29311
  this.defaultAuthRequest = defaultAuthRequest ?? null;
28792
29312
  this.getExitCode = getExitCode ?? (() => null);
28793
29313
  this.getRecentStderr = getRecentStderr ?? (() => "");
29314
+ this.sessionFailureEpoch = randomUUID2();
28794
29315
  this.clientInfo = null;
28795
29316
  this.clientCapabilities = null;
28796
29317
  this.terminalOutputMode = "terminal_output_delta";
@@ -28843,6 +29364,17 @@ var CodexAcpServer = class _CodexAcpServer {
28843
29364
  _meta: {
28844
29365
  steering: {
28845
29366
  supported: true
29367
+ },
29368
+ goal: {
29369
+ version: GOAL_EXTENSION_VERSION,
29370
+ controlMethod: GOAL_CONTROL_METHOD,
29371
+ actions: [...GOAL_CONTROL_ACTIONS]
29372
+ },
29373
+ [JETBRAINS_META_KEY]: {
29374
+ [AIR_META_KEY]: {
29375
+ [AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
29376
+ [AIR_EXTENSION_CAPABILITIES_KEY]: [AIR_SESSION_FAILURE_KEY]
29377
+ }
28846
29378
  }
28847
29379
  }
28848
29380
  };
@@ -28863,17 +29395,58 @@ var CodexAcpServer = class _CodexAcpServer {
28863
29395
  return await this.unstable_setSessionModel(this.parseLegacySetSessionModelParams(methodRequest.params));
28864
29396
  case SESSION_STEERING_METHOD:
28865
29397
  return await this.executeOrQueueSteeringRequest(this.parseSessionSteerParams(methodRequest.params));
28866
- case GOAL_CONTROL_METHOD: {
29398
+ case GOAL_CONTROL_METHOD:
29399
+ case LEGACY_GOAL_CONTROL_METHOD: {
28867
29400
  const sessionState = this.sessions.get(methodRequest.params.sessionId);
28868
29401
  if (!sessionState) {
28869
29402
  throw RequestError.invalidParams(void 0, `Unknown session: ${methodRequest.params.sessionId}`);
28870
29403
  }
28871
29404
  const sessionGeneration = this.getSessionGeneration(sessionState.sessionId);
28872
- if (methodRequest.params.action === "pause") {
29405
+ const goalControlGeneration = this.bumpGoalControlGeneration(sessionState.sessionId);
29406
+ if (methodRequest.params.action === "set") {
29407
+ const objective = methodRequest.params.objective;
29408
+ let updatedGoal = null;
29409
+ const turnCompleted = await this.runWithProcessCheck(() => this.codexAcpClient.setGoal(
29410
+ sessionState.sessionId,
29411
+ objective,
29412
+ void 0,
29413
+ (goal) => {
29414
+ updatedGoal = goal;
29415
+ }
29416
+ ));
29417
+ if (turnCompleted === null && updatedGoal !== null) {
29418
+ await this.startGoalContinuationIfCurrent(
29419
+ sessionState,
29420
+ sessionGeneration,
29421
+ goalControlGeneration,
29422
+ updatedGoal
29423
+ );
29424
+ }
29425
+ } else if (methodRequest.params.action === "pause") {
28873
29426
  const goal = await this.runWithProcessCheck(() => this.codexAcpClient.setGoalStatus(sessionState.sessionId, "paused"));
28874
29427
  if (this.goalPublishIsCurrent(sessionState, sessionGeneration)) {
28875
29428
  await this.publishGoalSnapshot(sessionState, toThreadGoalSnapshot(goal), false);
28876
29429
  }
29430
+ } else if (methodRequest.params.action === "resume") {
29431
+ let updatedGoal = null;
29432
+ const turnCompleted = await this.runWithProcessCheck(() => this.codexAcpClient.resumeGoal(
29433
+ sessionState.sessionId,
29434
+ void 0,
29435
+ (goal) => {
29436
+ updatedGoal = goal;
29437
+ }
29438
+ ));
29439
+ if (updatedGoal !== null && this.goalPublishIsCurrent(sessionState, sessionGeneration)) {
29440
+ await this.publishGoalSnapshot(sessionState, toThreadGoalSnapshot(updatedGoal), false);
29441
+ }
29442
+ if (turnCompleted === null && updatedGoal !== null) {
29443
+ await this.startGoalContinuationIfCurrent(
29444
+ sessionState,
29445
+ sessionGeneration,
29446
+ goalControlGeneration,
29447
+ updatedGoal
29448
+ );
29449
+ }
28877
29450
  } else if (methodRequest.params.action === "clear") {
28878
29451
  await this.runWithProcessCheck(() => this.codexAcpClient.clearGoal(sessionState.sessionId));
28879
29452
  if (this.goalPublishIsCurrent(sessionState, sessionGeneration)) {
@@ -28973,6 +29546,11 @@ Check ${configPath} and project .codex directories, especially their config.toml
28973
29546
  getSessionGeneration(sessionId) {
28974
29547
  return this.sessionGenerations.get(sessionId) ?? 0;
28975
29548
  }
29549
+ bumpGoalControlGeneration(sessionId) {
29550
+ const generation = (this.goalControlGenerations.get(sessionId) ?? 0) + 1;
29551
+ this.goalControlGenerations.set(sessionId, generation);
29552
+ return generation;
29553
+ }
28976
29554
  bumpSessionGeneration(sessionId) {
28977
29555
  const generation = this.getSessionGeneration(sessionId) + 1;
28978
29556
  this.sessionGenerations.set(sessionId, generation);
@@ -29171,6 +29749,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
29171
29749
  this.pendingTurnStarts.delete(params.sessionId);
29172
29750
  this.activePrompts.delete(params.sessionId);
29173
29751
  this.steeringQueues.delete(params.sessionId);
29752
+ this.goalControlGenerations.delete(params.sessionId);
29174
29753
  }
29175
29754
  this.endSessionCloseFence(params.sessionId);
29176
29755
  }
@@ -29215,9 +29794,10 @@ Check ${configPath} and project .codex directories, especially their config.toml
29215
29794
  ...this.createSessionConfigOptionsResponse(this.getSessionState(sessionId))
29216
29795
  };
29217
29796
  }
29218
- async authenticate(_params) {
29797
+ async authenticate(_params, requestId) {
29219
29798
  logger.log("Authenticate request received");
29220
- const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(_params));
29799
+ const elicitationRequester = this.createUrlElicitationRequester(requestId);
29800
+ const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(_params, elicitationRequester));
29221
29801
  if (!isAuthenticated) {
29222
29802
  logger.log("Authenticate request failed");
29223
29803
  throw RequestError.invalidParams();
@@ -29226,6 +29806,18 @@ Check ${configPath} and project .codex directories, especially their config.toml
29226
29806
  logger.log("Authenticate request completed");
29227
29807
  return {};
29228
29808
  }
29809
+ createUrlElicitationRequester(requestId) {
29810
+ if (requestId == null || !clientSupportsUrlElicitation(this.clientCapabilities)) {
29811
+ return void 0;
29812
+ }
29813
+ return {
29814
+ elicitUrl: (request) => this.connection.request(methods.client.elicitation.create, {
29815
+ mode: "url",
29816
+ requestId,
29817
+ ...request
29818
+ })
29819
+ };
29820
+ }
29229
29821
  async logout(_params) {
29230
29822
  logger.log("Logout request received");
29231
29823
  await this.runWithProcessCheck(() => this.codexAcpClient.logout());
@@ -29529,29 +30121,48 @@ Check ${configPath} and project .codex directories, especially their config.toml
29529
30121
  * fails or is cancelled before the turn starts.
29530
30122
  */
29531
30123
  async startNewTurnFromSteering(params) {
30124
+ await this.startNewTurnFromExternalPrompt(params, "Steering");
30125
+ return { outcome: "startedNewTurn" };
30126
+ }
30127
+ async startGoalContinuationIfCurrent(sessionState, sessionGeneration, goalControlGeneration, expectedGoal) {
30128
+ await this.startNewTurnFromExternalPrompt({
30129
+ sessionId: sessionState.sessionId,
30130
+ prompt: GOAL_CONTINUATION_PROMPT
30131
+ }, "Goal continuation", async () => {
30132
+ if (!this.goalPublishIsCurrent(sessionState, sessionGeneration) || this.goalControlGenerations.get(sessionState.sessionId) !== goalControlGeneration) {
30133
+ return false;
30134
+ }
30135
+ const currentGoal = await this.runWithProcessCheck(() => this.codexAcpClient.getGoal(sessionState.sessionId));
30136
+ return currentGoal?.status === "active" && currentGoal.objective === expectedGoal.objective && currentGoal.createdAt === expectedGoal.createdAt && this.goalControlGenerations.get(sessionState.sessionId) === goalControlGeneration;
30137
+ });
30138
+ }
30139
+ async startNewTurnFromExternalPrompt(params, source, canStart = async () => true) {
29532
30140
  const previousPrompt = this.activePrompts.get(params.sessionId);
29533
30141
  await previousPrompt?.completion;
29534
30142
  if (this.sessionIsClosing(params.sessionId)) {
29535
30143
  throw RequestError.invalidRequest(`Session ${params.sessionId} is closing`);
29536
30144
  }
30145
+ if (!await canStart()) {
30146
+ return false;
30147
+ }
29537
30148
  return await new Promise((resolve, reject) => {
29538
30149
  let turnStarted = false;
29539
30150
  const promptDone = this.prompt(params, void 0, () => {
29540
30151
  turnStarted = true;
29541
- logger.log("Steering session started a new turn", { sessionId: params.sessionId });
29542
- resolve({ outcome: "startedNewTurn" });
30152
+ logger.log(`${source} started a new turn`, { sessionId: params.sessionId });
30153
+ resolve(true);
29543
30154
  });
29544
30155
  promptDone.then(
29545
30156
  (response) => {
29546
30157
  if (!turnStarted && response.stopReason === "cancelled") {
29547
30158
  reject(RequestError.invalidRequest(`Session ${params.sessionId} was cancelled before the steering turn started`));
29548
30159
  } else {
29549
- resolve({ outcome: "startedNewTurn" });
30160
+ resolve(turnStarted);
29550
30161
  }
29551
30162
  },
29552
30163
  (error51) => {
29553
30164
  if (turnStarted) {
29554
- logger.error(`Steering-started prompt for session ${params.sessionId} failed`, error51);
30165
+ logger.error(`${source} prompt for session ${params.sessionId} failed`, error51);
29555
30166
  } else {
29556
30167
  reject(error51);
29557
30168
  }
@@ -29667,9 +30278,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
29667
30278
  await session.update({
29668
30279
  sessionUpdate: "session_info_update",
29669
30280
  _meta: {
29670
- codex: {
29671
- goal: snapshot
29672
- }
30281
+ goal: snapshot
29673
30282
  }
29674
30283
  });
29675
30284
  }
@@ -29966,8 +30575,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
29966
30575
  return `[@${name}](${uri})`;
29967
30576
  }
29968
30577
  if (uri.startsWith("file://")) {
29969
- const path6 = uri.replace("file://", "");
29970
- const fileName = path6.split("/").pop() ?? path6;
30578
+ const path7 = uri.replace("file://", "");
30579
+ const fileName = path7.split("/").pop() ?? path7;
29971
30580
  return `[@${fileName}](${uri})`;
29972
30581
  }
29973
30582
  return uri;
@@ -30220,6 +30829,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30220
30829
  prompt: params.prompt
30221
30830
  });
30222
30831
  const sessionState = this.getSessionState(params.sessionId);
30832
+ let recoverableSessionFailure = sessionState.sessionFailure;
30223
30833
  const promptStartTotalTokenUsage = sessionState.totalTokenUsage;
30224
30834
  sessionState.currentTurnId = null;
30225
30835
  sessionState.lastTokenUsage = null;
@@ -30234,11 +30844,21 @@ Check ${configPath} and project .codex directories, especially their config.toml
30234
30844
  };
30235
30845
  const disposePromptRequestCancellation = this.observePromptRequestCancellation(signal, sessionState, activePrompt);
30236
30846
  let eventHandler = null;
30847
+ let promptNotificationsActive = true;
30848
+ const clearRecoveredSessionFailure = async (handler) => {
30849
+ await handler.completeSuccessfulTurn(sessionState.currentTurnId);
30850
+ const current = sessionState.sessionFailure;
30851
+ if (recoverableSessionFailure !== void 0 && current !== void 0 && current.id === recoverableSessionFailure.id && current.revision === recoverableSessionFailure.revision) {
30852
+ await handler.clearSessionFailure();
30853
+ }
30854
+ };
30237
30855
  try {
30238
30856
  const promptEventHandler = new CodexEventHandler(
30239
30857
  this.connection,
30240
30858
  sessionState,
30241
- clientSupportsPlanUpdates(this.clientCapabilities)
30859
+ clientSupportsPlanUpdates(this.clientCapabilities),
30860
+ clientSupportsTypedSessionFailures(this.clientCapabilities),
30861
+ this.sessionFailureEpoch
30242
30862
  );
30243
30863
  eventHandler = promptEventHandler;
30244
30864
  const approvalHandler = new CodexApprovalHandler(this.connection, sessionState, activePrompt.signal);
@@ -30251,8 +30871,16 @@ Check ${configPath} and project .codex directories, especially their config.toml
30251
30871
  await this.codexAcpClient.subscribeToSessionEvents(
30252
30872
  params.sessionId,
30253
30873
  async (event) => {
30874
+ if (!promptNotificationsActive) {
30875
+ await promptEventHandler.handleSessionScopedNotification(event);
30876
+ return;
30877
+ }
30878
+ const completesActiveTurn = event.method === "turn/completed" && event.params.turn.id === sessionState.currentTurnId;
30254
30879
  await elicitationHandler.handleNotification(event);
30255
- return promptEventHandler.handleNotification(event);
30880
+ await promptEventHandler.handleNotification(event);
30881
+ if (completesActiveTurn) {
30882
+ promptNotificationsActive = false;
30883
+ }
30256
30884
  },
30257
30885
  approvalHandler,
30258
30886
  elicitationHandler
@@ -30302,22 +30930,38 @@ Check ${configPath} and project .codex directories, especially their config.toml
30302
30930
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30303
30931
  }
30304
30932
  if (commandResult.handled) {
30933
+ promptNotificationsActive = false;
30305
30934
  logger.log("Prompt handled by a command");
30306
30935
  await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
30936
+ await eventHandler.flushPendingErrors();
30937
+ await eventHandler.flushPendingErrorsAsSessionScoped();
30938
+ if (commandResult.turnCompleted) {
30939
+ await eventHandler.handleFailedTurn(commandResult.turnCompleted.turn);
30940
+ }
30307
30941
  if (commandResult.turnCompleted?.turn.status === "interrupted") {
30308
- await this.notifyConversationInterrupted(params.sessionId);
30309
30942
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30310
30943
  }
30311
30944
  const error52 = eventHandler.getFailure();
30312
30945
  if (error52) {
30313
30946
  throw error52;
30314
30947
  }
30948
+ const terminalFailure2 = this.terminalFailurePromptResponse(
30949
+ sessionState,
30950
+ eventHandler,
30951
+ commandResult.turnCompleted?.turn.id ?? sessionState.currentTurnId,
30952
+ promptStartTotalTokenUsage
30953
+ );
30954
+ if (terminalFailure2) {
30955
+ return terminalFailure2;
30956
+ }
30957
+ await clearRecoveredSessionFailure(eventHandler);
30315
30958
  return {
30316
30959
  stopReason: "end_turn",
30317
30960
  usage: this.buildPromptUsage(sessionState, promptStartTotalTokenUsage),
30318
30961
  _meta: this.buildQuotaMeta(sessionState)
30319
30962
  };
30320
30963
  }
30964
+ const effectiveParams = commandResult.prompt === void 0 ? params : { ...params, prompt: commandResult.prompt };
30321
30965
  if (this.sessionIsClosing(params.sessionId)) {
30322
30966
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30323
30967
  }
@@ -30330,7 +30974,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30330
30974
  reason: sessionState.account?.type === "apiKey" ? "API key" : "model lacks reasoning"
30331
30975
  });
30332
30976
  }
30333
- if (!sessionState.supportedInputModalities.includes("image") && params.prompt.some((b) => b.type === "image")) {
30977
+ if (!sessionState.supportedInputModalities.includes("image") && effectiveParams.prompt.some((b) => b.type === "image")) {
30334
30978
  throw RequestError.invalidRequest("The current model does not support image input");
30335
30979
  }
30336
30980
  const agentMode = sessionState.agentMode;
@@ -30341,7 +30985,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30341
30985
  ensurePendingTurnStart();
30342
30986
  const sendPromptPromise = this.runWithProcessCheck(
30343
30987
  () => this.codexAcpClient.sendPrompt(
30344
- params,
30988
+ effectiveParams,
30345
30989
  agentMode,
30346
30990
  sessionState.approvalsReviewer,
30347
30991
  modelId,
@@ -30377,15 +31021,26 @@ Check ${configPath} and project .codex directories, especially their config.toml
30377
31021
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30378
31022
  }
30379
31023
  await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
31024
+ await eventHandler.flushPendingErrors();
31025
+ await eventHandler.handleFailedTurn(turnCompleted.turn);
31026
+ promptNotificationsActive = false;
30380
31027
  if (turnCompleted.turn.status === "interrupted") {
30381
31028
  await eventHandler.flushPendingPlanUpdates();
30382
- await this.notifyConversationInterrupted(params.sessionId);
30383
31029
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30384
31030
  }
30385
31031
  const error51 = eventHandler.getFailure();
30386
31032
  if (error51) {
30387
31033
  throw error51;
30388
31034
  }
31035
+ const terminalFailure = this.terminalFailurePromptResponse(
31036
+ sessionState,
31037
+ eventHandler,
31038
+ turnCompleted.turn.id,
31039
+ promptStartTotalTokenUsage
31040
+ );
31041
+ if (terminalFailure) {
31042
+ return terminalFailure;
31043
+ }
30389
31044
  await eventHandler.flushPendingPlanUpdates();
30390
31045
  const completedPlan = eventHandler.takeCompletedPlan();
30391
31046
  if (completedPlan !== null && sessionState.collaborationMode === PLAN_COLLABORATION_MODE && !this.promptShouldStop(params.sessionId, activePrompt)) {
@@ -30409,6 +31064,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30409
31064
  prompt: [{ type: "text", text: "Implement the approved plan." }]
30410
31065
  };
30411
31066
  activePrompt.currentTurn = null;
31067
+ sessionState.currentTurnId = null;
30412
31068
  const implementationPromise = this.runWithProcessCheck(
30413
31069
  () => this.codexAcpClient.sendPrompt(
30414
31070
  implementationRequest,
@@ -30427,6 +31083,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
30427
31083
  return;
30428
31084
  }
30429
31085
  sessionState.currentTurnId = turnId;
31086
+ recoverableSessionFailure = sessionState.sessionFailure;
31087
+ promptNotificationsActive = true;
30430
31088
  },
30431
31089
  () => this.promptShouldStop(params.sessionId, activePrompt)
30432
31090
  )
@@ -30445,17 +31103,29 @@ Check ${configPath} and project .codex directories, especially their config.toml
30445
31103
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30446
31104
  }
30447
31105
  await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
31106
+ await eventHandler.flushPendingErrors();
31107
+ await eventHandler.handleFailedTurn(turnCompleted.turn);
31108
+ promptNotificationsActive = false;
30448
31109
  if (turnCompleted.turn.status === "interrupted") {
30449
31110
  await eventHandler.flushPendingPlanUpdates();
30450
- await this.notifyConversationInterrupted(params.sessionId);
30451
31111
  return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
30452
31112
  }
30453
31113
  const implementationError = eventHandler.getFailure();
30454
31114
  if (implementationError) {
30455
31115
  throw implementationError;
30456
31116
  }
31117
+ const implementationFailure = this.terminalFailurePromptResponse(
31118
+ sessionState,
31119
+ eventHandler,
31120
+ turnCompleted.turn.id,
31121
+ promptStartTotalTokenUsage
31122
+ );
31123
+ if (implementationFailure) {
31124
+ return implementationFailure;
31125
+ }
30457
31126
  }
30458
31127
  }
31128
+ await clearRecoveredSessionFailure(eventHandler);
30459
31129
  await this.publishFallbackSessionTitle(
30460
31130
  sessionState,
30461
31131
  this.createPromptFallbackTitle(params.prompt)
@@ -30467,8 +31137,30 @@ Check ${configPath} and project .codex directories, especially their config.toml
30467
31137
  };
30468
31138
  } catch (err) {
30469
31139
  logger.error(`Prompt for session ${params.sessionId} failed`, err);
31140
+ if (activePrompt.signal.aborted || this.sessionIsClosing(params.sessionId)) {
31141
+ return this.cancelledPromptResponse(sessionState, promptStartTotalTokenUsage);
31142
+ }
31143
+ const isProcessExit = err instanceof RequestError && err.code === CODEX_PROCESS_EXITED_ERROR_CODE;
31144
+ const isUnexpectedFailure = !(err instanceof RequestError);
31145
+ if (eventHandler !== null && clientSupportsTypedSessionFailures(this.clientCapabilities) && (isProcessExit || isUnexpectedFailure)) {
31146
+ eventHandler.recordSyntheticTerminalFailure(
31147
+ isProcessExit ? "transport_lost" : "internal_error",
31148
+ sessionState.currentTurnId
31149
+ );
31150
+ const failureResponse = this.terminalFailurePromptResponse(
31151
+ sessionState,
31152
+ eventHandler,
31153
+ sessionState.currentTurnId,
31154
+ promptStartTotalTokenUsage,
31155
+ true
31156
+ );
31157
+ if (failureResponse !== null) {
31158
+ return failureResponse;
31159
+ }
31160
+ }
30470
31161
  throw err;
30471
31162
  } finally {
31163
+ promptNotificationsActive = false;
30472
31164
  logger.log("Prompt completed", { sessionId: params.sessionId });
30473
31165
  await eventHandler?.dispose();
30474
31166
  disposePromptRequestCancellation();
@@ -30539,14 +31231,19 @@ Check ${configPath} and project .codex directories, especially their config.toml
30539
31231
  _meta: this.buildQuotaMeta(sessionState)
30540
31232
  };
30541
31233
  }
30542
- async notifyConversationInterrupted(sessionId) {
30543
- if (this.sessionIsClosing(sessionId) || !this.sessions.has(sessionId)) {
30544
- return;
31234
+ terminalFailurePromptResponse(sessionState, eventHandler, turnId, promptStartTotalTokenUsage, allowUnattributed = false) {
31235
+ const failureMeta = eventHandler.getTerminalSessionFailureMeta(turnId, allowUnattributed);
31236
+ if (failureMeta === null) {
31237
+ return null;
30545
31238
  }
30546
- await this.connection.notify(methods.client.session.update, {
30547
- sessionId,
30548
- update: createAgentTextMessageChunk("*Conversation interrupted*")
30549
- });
31239
+ return {
31240
+ stopReason: "end_turn",
31241
+ usage: this.buildPromptUsage(sessionState, promptStartTotalTokenUsage),
31242
+ _meta: {
31243
+ ...this.buildQuotaMeta(sessionState),
31244
+ ...failureMeta
31245
+ }
31246
+ };
30550
31247
  }
30551
31248
  buildQuotaMeta(sessionState) {
30552
31249
  const lastTokenUsage = sessionState.lastTokenUsage;
@@ -30571,7 +31268,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30571
31268
  return await operation();
30572
31269
  } catch (err) {
30573
31270
  const exitCode = this.getExitCode();
30574
- const requestErrorCode = 1001;
31271
+ const requestErrorCode = CODEX_PROCESS_EXITED_ERROR_CODE;
30575
31272
  if (exitCode == 3221225781) {
30576
31273
  throw new RequestError(requestErrorCode, `VC++ redistributable should be installed`);
30577
31274
  }
@@ -31066,6 +31763,9 @@ var CodexAppServerClient = class {
31066
31763
  async accountLogin(params) {
31067
31764
  return await this.sendRequest({ method: "account/login/start", params });
31068
31765
  }
31766
+ async accountLoginCancel(params) {
31767
+ return await this.sendRequest({ method: "account/login/cancel", params });
31768
+ }
31069
31769
  async accountLogout() {
31070
31770
  return await this.sendRequest({ method: "account/logout", params: void 0 });
31071
31771
  }
@@ -31590,10 +32290,17 @@ var sessionSteerParamsParser = external_exports.object({
31590
32290
  sessionId: external_exports.string(),
31591
32291
  prompt: external_exports.array(external_exports.any())
31592
32292
  }).passthrough();
31593
- var goalControlParamsParser = external_exports.object({
31594
- sessionId: external_exports.string(),
31595
- action: external_exports.enum(["pause", "clear"])
31596
- }).passthrough();
32293
+ var goalControlParamsParser = external_exports.discriminatedUnion("action", [
32294
+ external_exports.object({
32295
+ sessionId: external_exports.string(),
32296
+ action: external_exports.literal("set"),
32297
+ objective: external_exports.string().trim().min(1)
32298
+ }).passthrough(),
32299
+ external_exports.object({
32300
+ sessionId: external_exports.string(),
32301
+ action: external_exports.enum(["pause", "resume", "clear"])
32302
+ }).passthrough()
32303
+ ]);
31597
32304
  if (process.argv.includes("--version")) {
31598
32305
  console.log(`${package_default.name} ${package_default.version}`);
31599
32306
  process.exit(0);
@@ -31673,5 +32380,5 @@ function startAcpServer() {
31673
32380
  codexAcpServer = null;
31674
32381
  }
31675
32382
  });
31676
- }).onRequest(methods.agent.initialize, (ctx) => getAgent().initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => getAgent().newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => getAgent().loadSession(ctx.params)).onRequest(methods.agent.session.list, (ctx) => getAgent().listSessions(ctx.params)).onRequest(methods.agent.session.delete, (ctx) => getAgent().deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => getAgent().resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => getAgent().closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => getAgent().setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => getAgent().setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => getAgent().authenticate(ctx.params)).onRequest(methods.agent.logout, (ctx) => getAgent().logout(ctx.params)).onRequest(methods.agent.providers.list, (ctx) => getAgent().listProviders(ctx.params)).onRequest(methods.agent.providers.set, (ctx) => getAgent().setProvider(ctx.params)).onRequest(methods.agent.providers.disable, (ctx) => getAgent().disableProvider(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => getAgent().prompt(ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => getAgent().cancel(ctx.params)).onRequest("authentication/status", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/status", ctx.params)).onRequest("authentication/logout", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/logout", ctx.params)).onRequest(LEGACY_SET_SESSION_MODEL_METHOD, legacySetSessionModelParamsParser, (ctx) => getAgent().extMethod(LEGACY_SET_SESSION_MODEL_METHOD, ctx.params)).onRequest(SESSION_STEERING_METHOD, sessionSteerParamsParser, (ctx) => getAgent().extMethod(SESSION_STEERING_METHOD, ctx.params)).onRequest(GOAL_CONTROL_METHOD, goalControlParamsParser, (ctx) => getAgent().extMethod(GOAL_CONTROL_METHOD, ctx.params)).connect(acpJsonStream);
32383
+ }).onRequest(methods.agent.initialize, (ctx) => getAgent().initialize(ctx.params)).onRequest(methods.agent.session.new, (ctx) => getAgent().newSession(ctx.params)).onRequest(methods.agent.session.load, (ctx) => getAgent().loadSession(ctx.params)).onRequest(methods.agent.session.list, (ctx) => getAgent().listSessions(ctx.params)).onRequest(methods.agent.session.delete, (ctx) => getAgent().deleteSession(ctx.params)).onRequest(methods.agent.session.resume, (ctx) => getAgent().resumeSession(ctx.params)).onRequest(methods.agent.session.close, (ctx) => getAgent().closeSession(ctx.params)).onRequest(methods.agent.session.setMode, (ctx) => getAgent().setSessionMode(ctx.params)).onRequest(methods.agent.session.setConfigOption, (ctx) => getAgent().setSessionConfigOption(ctx.params)).onRequest(methods.agent.authenticate, (ctx) => getAgent().authenticate(ctx.params, ctx.requestId)).onRequest(methods.agent.logout, (ctx) => getAgent().logout(ctx.params)).onRequest(methods.agent.providers.list, (ctx) => getAgent().listProviders(ctx.params)).onRequest(methods.agent.providers.set, (ctx) => getAgent().setProvider(ctx.params)).onRequest(methods.agent.providers.disable, (ctx) => getAgent().disableProvider(ctx.params)).onRequest(methods.agent.session.prompt, (ctx) => getAgent().prompt(ctx.params, ctx.signal)).onNotification(methods.agent.session.cancel, (ctx) => getAgent().cancel(ctx.params)).onRequest("authentication/status", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/status", ctx.params)).onRequest("authentication/logout", emptyExtensionParamsParser, (ctx) => getAgent().extMethod("authentication/logout", ctx.params)).onRequest(LEGACY_SET_SESSION_MODEL_METHOD, legacySetSessionModelParamsParser, (ctx) => getAgent().extMethod(LEGACY_SET_SESSION_MODEL_METHOD, ctx.params)).onRequest(SESSION_STEERING_METHOD, sessionSteerParamsParser, (ctx) => getAgent().extMethod(SESSION_STEERING_METHOD, ctx.params)).onRequest(GOAL_CONTROL_METHOD, goalControlParamsParser, (ctx) => getAgent().extMethod(GOAL_CONTROL_METHOD, ctx.params)).connect(acpJsonStream);
31677
32384
  }