@agentclientprotocol/codex-acp 2.5.1-preview.10 → 2.5.1-preview.11

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 +148 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -32216,6 +32216,76 @@ function normalizeJsonObject(value) {
32216
32216
  );
32217
32217
  }
32218
32218
 
32219
+ // src/AcpV2SessionInfo.ts
32220
+ var AcpV2SessionInfo = class {
32221
+ constructor(send, initialMetadata = null) {
32222
+ this.send = send;
32223
+ this.applyMetadata(JSON.parse(JSON.stringify({ _meta: initialMetadata }))._meta);
32224
+ }
32225
+ send;
32226
+ metadata = /* @__PURE__ */ new Map();
32227
+ tail = Promise.resolve();
32228
+ disposed = false;
32229
+ update(update, notificationMetadata) {
32230
+ let copy;
32231
+ try {
32232
+ copy = JSON.parse(JSON.stringify({ update, _meta: notificationMetadata }));
32233
+ } catch (error62) {
32234
+ return Promise.reject(error62);
32235
+ }
32236
+ return this.enqueue(async () => {
32237
+ this.applyMetadata(copy.update._meta);
32238
+ await this.publish(copy.update, copy._meta);
32239
+ });
32240
+ }
32241
+ patchMetadata(change) {
32242
+ return this.enqueue(async () => {
32243
+ const current = JSON.parse(JSON.stringify(Object.fromEntries(this.metadata)));
32244
+ const patch = change(current);
32245
+ if (patch === null) return;
32246
+ const update = JSON.parse(JSON.stringify({ sessionUpdate: "session_info_update", _meta: patch }));
32247
+ this.applyMetadata(update._meta);
32248
+ await this.publish(update);
32249
+ });
32250
+ }
32251
+ seedMetadata(metadata) {
32252
+ const copy = JSON.parse(JSON.stringify({ _meta: metadata }))._meta;
32253
+ return this.enqueue(async () => {
32254
+ this.applyMetadata(copy);
32255
+ });
32256
+ }
32257
+ snapshot(title) {
32258
+ return this.enqueue(async () => {
32259
+ await this.publish({ sessionUpdate: "session_info_update", title, _meta: null });
32260
+ if (this.metadata.size > 0) {
32261
+ await this.publish({ sessionUpdate: "session_info_update", _meta: Object.fromEntries(this.metadata) });
32262
+ }
32263
+ });
32264
+ }
32265
+ dispose() {
32266
+ this.disposed = true;
32267
+ this.metadata.clear();
32268
+ }
32269
+ applyMetadata(patch) {
32270
+ if (patch === null) this.metadata.clear();
32271
+ else if (isRecord2(patch)) for (const [key, value] of Object.entries(patch)) {
32272
+ if (value === null) this.metadata.delete(key);
32273
+ else this.metadata.set(key, value);
32274
+ }
32275
+ }
32276
+ enqueue(operation) {
32277
+ const next = this.tail.then(async () => {
32278
+ if (!this.disposed) await operation();
32279
+ });
32280
+ this.tail = next.catch(() => {
32281
+ });
32282
+ return next;
32283
+ }
32284
+ publish(update, notificationMetadata) {
32285
+ return this.disposed ? Promise.resolve() : this.send(update, notificationMetadata);
32286
+ }
32287
+ };
32288
+
32219
32289
  // src/JsonSnapshot.ts
32220
32290
  import { types } from "node:util";
32221
32291
  var JsonObject = class {
@@ -32773,6 +32843,10 @@ var AcpV2Connection = class {
32773
32843
  if (method === methods2.client.elicitation.complete) return this.sendElicitationCompletion(params);
32774
32844
  const sessionId = clientNotificationSessionId(method, params);
32775
32845
  if (sessionId !== null && this.sessionDelivery && !this.sessionDelivery.canPublishSession(sessionId)) return Promise.resolve();
32846
+ if (sessionId !== null) {
32847
+ const { update, _meta } = params;
32848
+ if (SessionUpdate.isSessionInfoUpdate(update)) return this.sessionInfoFor(sessionId).update(update, _meta);
32849
+ }
32776
32850
  return client.notify(method, params);
32777
32851
  },
32778
32852
  request: (method, params, options) => {
@@ -32793,6 +32867,7 @@ var AcpV2Connection = class {
32793
32867
  client;
32794
32868
  isTurnRunning = () => true;
32795
32869
  foreground = /* @__PURE__ */ new Map();
32870
+ sessionInfo = /* @__PURE__ */ new Map();
32796
32871
  sessionDelivery = null;
32797
32872
  sendElicitationCompletion;
32798
32873
  setClientDelivery(delivery) {
@@ -32817,9 +32892,12 @@ var AcpV2Connection = class {
32817
32892
  * Sends a session update, rendered in the v2 wire shape, through the v2 `session/update`
32818
32893
  * binding. One update can render to several v2 updates (or none), sent in order.
32819
32894
  */
32820
- async updateSession(sessionId, update) {
32895
+ async updateSession(sessionId, update, metadata) {
32821
32896
  for (const v2Update of toV2SessionUpdates(update)) {
32822
- await this.client.notify(methods2.client.session.update, { sessionId, update: v2Update });
32897
+ await this.client.notify(
32898
+ methods2.client.session.update,
32899
+ { sessionId, update: v2Update, ...metadata !== void 0 ? { _meta: metadata } : {} }
32900
+ );
32823
32901
  }
32824
32902
  }
32825
32903
  /** Sends a `state_update`, which only exists on v2 and so needs no rendering. */
@@ -32832,6 +32910,20 @@ var AcpV2Connection = class {
32832
32910
  snapshotForegroundState(sessionId) {
32833
32911
  return this.foregroundFor(sessionId).snapshot();
32834
32912
  }
32913
+ resetSessionInfo(sessionId, metadata) {
32914
+ this.sessionInfo.get(sessionId)?.dispose();
32915
+ this.sessionInfo.delete(sessionId);
32916
+ this.sessionInfoFor(sessionId, metadata);
32917
+ }
32918
+ refreshSessionInfo(sessionId, metadata) {
32919
+ return metadata ? this.sessionInfoFor(sessionId).seedMetadata(metadata) : Promise.resolve();
32920
+ }
32921
+ snapshotSessionInfo(sessionId, title) {
32922
+ return this.sessionInfoFor(sessionId).snapshot(title);
32923
+ }
32924
+ patchSessionMetadata(sessionId, change) {
32925
+ return this.sessionInfoFor(sessionId).patchMetadata(change);
32926
+ }
32835
32927
  startForegroundItem(sessionId, itemId) {
32836
32928
  return this.foregroundFor(sessionId).startItem(itemId);
32837
32929
  }
@@ -32844,6 +32936,28 @@ var AcpV2Connection = class {
32844
32936
  forgetSession(sessionId) {
32845
32937
  this.foreground.get(sessionId)?.dispose();
32846
32938
  this.foreground.delete(sessionId);
32939
+ this.sessionInfo.get(sessionId)?.dispose();
32940
+ this.sessionInfo.delete(sessionId);
32941
+ }
32942
+ sessionInfoFor(sessionId, metadata = null) {
32943
+ if (this.sessionDelivery && !this.sessionDelivery.canPublishSession(sessionId)) {
32944
+ const closed = new AcpV2SessionInfo(async () => {
32945
+ });
32946
+ closed.dispose();
32947
+ return closed;
32948
+ }
32949
+ let info = this.sessionInfo.get(sessionId);
32950
+ if (!info) {
32951
+ info = new AcpV2SessionInfo((update, notificationMetadata) => {
32952
+ if (this.sessionDelivery && !this.sessionDelivery.canPublishSession(sessionId)) return Promise.resolve();
32953
+ return this.transportClient.notify(
32954
+ methods2.client.session.update,
32955
+ { sessionId, update, ...notificationMetadata !== void 0 ? { _meta: notificationMetadata } : {} }
32956
+ );
32957
+ }, metadata);
32958
+ this.sessionInfo.set(sessionId, info);
32959
+ }
32960
+ return info;
32847
32961
  }
32848
32962
  foregroundFor(sessionId, running = false) {
32849
32963
  if (this.sessionDelivery && !this.sessionDelivery.canPublishSession(sessionId)) {
@@ -32934,7 +33048,7 @@ var AcpV2Connection = class {
32934
33048
  }
32935
33049
  if (method === methods.client.session.update) {
32936
33050
  const notification = params;
32937
- return this.updateSession(notification.sessionId, notification.update);
33051
+ return this.updateSession(notification.sessionId, notification.update, notification._meta);
32938
33052
  }
32939
33053
  if (method === methods.client.elicitation.complete) {
32940
33054
  return this.completeElicitation(params);
@@ -33003,6 +33117,10 @@ var ACPSessionConnection = class _ACPSessionConnection {
33003
33117
  forSession(sessionId) {
33004
33118
  return new _ACPSessionConnection(this.connection, sessionId);
33005
33119
  }
33120
+ /** Domain writers can rebuild an owned metadata value without changing v2's shallow patch semantics. */
33121
+ patchSessionMetadata(change) {
33122
+ return this.v2Connection?.patchSessionMetadata(this.sessionId, change) ?? Promise.resolve();
33123
+ }
33006
33124
  /** Replay shares live report filtering, with v2 entity initialization after conversion. */
33007
33125
  replayUpdate(update, initialized) {
33008
33126
  return this.v2Connection ? this.v2Connection.replaySessionUpdate(this.sessionId, update, initialized) : this.update(update);
@@ -37765,7 +37883,17 @@ ${diff}`, "");
37765
37883
  }
37766
37884
  }
37767
37885
  async clearSessionFailure() {
37886
+ const failure3 = this.sessionState.sessionFailure;
37768
37887
  delete this.sessionState.sessionFailure;
37888
+ if (!failure3 || this.session.protocolVersion !== 2) return;
37889
+ await this.session.patchSessionMetadata((metadata) => {
37890
+ const jetbrains = recordOrNull(metadata[JETBRAINS_META_KEY]);
37891
+ const air = recordOrNull(jetbrains?.[AIR_META_KEY]);
37892
+ const published = recordOrNull(air?.[AIR_SESSION_FAILURE_KEY]);
37893
+ if (!air || published?.["id"] !== failure3.id || published?.["revision"] !== failure3.revision) return null;
37894
+ const { [AIR_SESSION_FAILURE_KEY]: _failure, ...currentAir } = air;
37895
+ return { [JETBRAINS_META_KEY]: { ...jetbrains, [AIR_META_KEY]: currentAir } };
37896
+ });
37769
37897
  }
37770
37898
  async completeSuccessfulTurn(turnId) {
37771
37899
  this.lastSessionNotice = void 0;
@@ -37773,7 +37901,7 @@ ${diff}`, "");
37773
37901
  const active = this.sessionState.sessionFailure;
37774
37902
  if (active?.id !== this.activeFailureIdByScope.get(turnId) || active?.severity !== "warning") return;
37775
37903
  this.activeFailureIdByScope.delete(turnId);
37776
- delete this.sessionState.sessionFailure;
37904
+ await this.clearSessionFailure();
37777
37905
  }
37778
37906
  async handleFailedTurn(turn) {
37779
37907
  if (turn.status === "failed" && this.isAuthenticationRequiredError(turn.error?.codexErrorInfo ?? null)) {
@@ -38502,7 +38630,7 @@ ${event.details}` : event.summary;
38502
38630
  if (activeId === void 0 || this.failuresById.get(activeId)?.severity !== "warning") return;
38503
38631
  this.activeFailureIdByScope.delete(turnId);
38504
38632
  if (this.sessionState.sessionFailure?.id === activeId) {
38505
- delete this.sessionState.sessionFailure;
38633
+ void this.clearSessionFailure().catch((error62) => logger.error("Failed to clear session failure metadata", error62));
38506
38634
  }
38507
38635
  }
38508
38636
  recordRetryWarning(params, attributeToTurn = true) {
@@ -41095,7 +41223,7 @@ var package_default = {
41095
41223
  publishConfig: {
41096
41224
  access: "public"
41097
41225
  },
41098
- version: "2.5.1-preview.10",
41226
+ version: "2.5.1-preview.11",
41099
41227
  description: "",
41100
41228
  main: "dist/index.js",
41101
41229
  bin: {
@@ -50702,7 +50830,7 @@ You have been logged out. Please try again.`);
50702
50830
  this.sessionIndex.titleWriter(sessionId)
50703
50831
  );
50704
50832
  sessionState.promptSuggestions = this.createPromptSuggestions(sessionState);
50705
- this.installSessionState(sessionState);
50833
+ this.installSessionState(sessionState, sessionMetadata.threadStatus);
50706
50834
  AcpV2Connection.of(this.connection)?.restoreForegroundState(sessionId, sessionMetadata.threadStatus?.type === "active");
50707
50835
  this.recovery?.markLoaded(sessionState, openGeneration);
50708
50836
  if (settleTrackerReady) {
@@ -50865,12 +50993,22 @@ You have been logged out. Please try again.`);
50865
50993
  new ACPSessionConnection(this.connection, sessionId)
50866
50994
  );
50867
50995
  }
50868
- installSessionState(sessionState) {
50996
+ installSessionState(sessionState, threadStatus) {
50869
50997
  const previous = this.sessions.get(sessionState.sessionId);
50870
50998
  previous?.asyncTasks.clear();
50871
50999
  void previous?.promptSuggestions?.clear();
50872
51000
  this.sessions.set(sessionState.sessionId, sessionState);
50873
51001
  this.clientDelivery.openSession(sessionState.sessionId);
51002
+ const v2 = AcpV2Connection.of(this.connection);
51003
+ if (v2) {
51004
+ const metadata = threadStatus ? { codex: { threadStatus } } : null;
51005
+ if (previous) {
51006
+ if (previous.sessionFailure) sessionState.sessionFailure = previous.sessionFailure;
51007
+ void v2.refreshSessionInfo(sessionState.sessionId, metadata);
51008
+ } else {
51009
+ v2.resetSessionInfo(sessionState.sessionId, metadata);
51010
+ }
51011
+ }
50874
51012
  }
50875
51013
  /**
50876
51014
  * Installs a baseline session-scoped subscription, so a Codex-initiated turn starting before
@@ -51173,10 +51311,7 @@ You have been logged out. Please try again.`);
51173
51311
  async snapshotSessionStateV2(sessionId) {
51174
51312
  await this.codexAcpClient.waitForSessionNotifications(sessionId);
51175
51313
  const state = this.getSessionState(sessionId);
51176
- await new ACPSessionConnection(this.connection, sessionId).update({
51177
- sessionUpdate: "session_info_update",
51178
- title: state.sessionTitle
51179
- });
51314
+ await AcpV2Connection.of(this.connection).snapshotSessionInfo(sessionId, state.sessionTitle);
51180
51315
  await AcpV2Connection.of(this.connection).snapshotForegroundState(sessionId);
51181
51316
  }
51182
51317
  async forkSession(params) {
@@ -52499,7 +52634,7 @@ You have been logged out. Please try again.`);
52499
52634
  this.sessionIndex.titleWriter(sessionId)
52500
52635
  );
52501
52636
  sessionState.promptSuggestions = this.createPromptSuggestions(sessionState);
52502
- this.installSessionState(sessionState);
52637
+ this.installSessionState(sessionState, thread.status);
52503
52638
  AcpV2Connection.of(this.connection)?.restoreForegroundState(sessionId, thread.status.type === "active");
52504
52639
  this.recovery?.markLoaded(sessionState, openGeneration);
52505
52640
  if (knownAccount === "pending") {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.5.1-preview.10",
6
+ "version": "2.5.1-preview.11",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {