@agentclientprotocol/codex-acp 1.1.8 → 1.1.10

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 +226 -78
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -13,8 +13,9 @@ Use [OpenAI Codex](https://github.com/openai/codex) from [Agent Client Protocol]
13
13
  - Text prompts, embedded context, images, resource links, and additional workspace directories.
14
14
  - Shell command, file change, permission request, MCP tool call, terminal output, reasoning, plan, web search, image generation, image view, token usage, and review events.
15
15
  - Subagent launches as standard ACP tool calls, with Codex thread identity and activity details in namespaced `_meta.codex.subagent` metadata.
16
+ - Session-scoped long-running goals through the provider-neutral [goal extension](docs/goal-extension.md).
16
17
  - Client-provided MCP servers over command-based stdio config and HTTP transport.
17
- - Slash commands: `/status`, `/mcp`, `/skills`, `/review`, `/review-branch`, `/review-commit`, `/compact`, and `/logout`, as well as configured skills.
18
+ - Slash commands: `/status`, `/mcp`, `/skills`, `/goal`, `/review`, `/review-branch`, `/review-commit`, `/compact`, and `/logout`, as well as configured skills.
18
19
 
19
20
  ## Installation
20
21
 
package/dist/index.js CHANGED
@@ -23556,22 +23556,37 @@ function createAgentTextThoughtChunk(text, messageId, meta3) {
23556
23556
  return createAgentThoughtChunk({ type: "text", text }, messageId, meta3);
23557
23557
  }
23558
23558
 
23559
- // src/AcpExtensions.ts
23560
- var LEGACY_SET_SESSION_MODEL_METHOD = "session/set_model";
23561
- var SESSION_STEERING_METHOD = "_session/steering";
23562
- var GOAL_CONTROL_METHOD = "_codex/session/goal_control";
23563
- function isExtMethodRequest(request) {
23564
- 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;
23565
- }
23559
+ // src/GoalExtension.ts
23560
+ var GOAL_EXTENSION_VERSION = 1;
23561
+ var GOAL_CONTROL_METHOD = "_session/goal";
23562
+ var LEGACY_GOAL_CONTROL_METHOD = "_codex/session/goal_control";
23563
+ var GOAL_CONTROL_ACTIONS = ["pause", "clear"];
23566
23564
 
23567
23565
  // src/ThreadGoalSnapshot.ts
23566
+ function toGoalStatus(status) {
23567
+ switch (status) {
23568
+ case "active":
23569
+ case "paused":
23570
+ case "blocked":
23571
+ case "complete":
23572
+ return status;
23573
+ case "usageLimited":
23574
+ case "budgetLimited":
23575
+ return "limited";
23576
+ }
23577
+ }
23578
+ function toUnixMilliseconds(timestampSeconds) {
23579
+ return timestampSeconds * 1e3;
23580
+ }
23568
23581
  function toThreadGoalSnapshot(goal) {
23569
23582
  return {
23570
23583
  objective: goal.objective.trim(),
23571
- status: goal.status,
23584
+ status: toGoalStatus(goal.status),
23572
23585
  tokenBudget: goal.tokenBudget,
23586
+ tokensUsed: goal.tokensUsed,
23573
23587
  timeUsedSeconds: goal.timeUsedSeconds,
23574
- createdAt: goal.createdAt,
23588
+ createdAt: toUnixMilliseconds(goal.createdAt),
23589
+ updatedAt: toUnixMilliseconds(goal.updatedAt),
23575
23590
  controlMethod: GOAL_CONTROL_METHOD
23576
23591
  };
23577
23592
  }
@@ -23582,8 +23597,8 @@ function sameThreadGoalSnapshot(left, right) {
23582
23597
  }
23583
23598
 
23584
23599
  // src/CodexEventHandler.ts
23585
- var CodexEventHandler = class {
23586
- connection;
23600
+ var CodexEventHandler = class _CodexEventHandler {
23601
+ static PLAN_UPDATE_INTERVAL_MS = 150;
23587
23602
  sessionState;
23588
23603
  supportsPlanUpdates;
23589
23604
  failure = null;
@@ -23593,15 +23608,21 @@ var CodexEventHandler = class {
23593
23608
  activeImageGenerationItems = /* @__PURE__ */ new Set();
23594
23609
  emittedImageViewItems = /* @__PURE__ */ new Set();
23595
23610
  planDeltaTextByItemId = /* @__PURE__ */ new Map();
23611
+ pendingPlanItemIds = /* @__PURE__ */ new Set();
23612
+ lastEmittedPlanTextByItemId = /* @__PURE__ */ new Map();
23613
+ session;
23614
+ planUpdateTimer = null;
23615
+ planUpdateChain = Promise.resolve();
23616
+ disposed = false;
23596
23617
  seenReasoningDeltaItemIds = /* @__PURE__ */ new Set();
23597
23618
  terminalCommandIds = /* @__PURE__ */ new Set();
23598
23619
  terminalCommandOutputIds = /* @__PURE__ */ new Set();
23599
23620
  agentMessagePhases = /* @__PURE__ */ new Map();
23600
23621
  activeSubAgentActivities = /* @__PURE__ */ new Set();
23601
23622
  constructor(connection, sessionState, supportsPlanUpdates = false) {
23602
- this.connection = connection;
23603
23623
  this.sessionState = sessionState;
23604
23624
  this.supportsPlanUpdates = supportsPlanUpdates;
23625
+ this.session = new ACPSessionConnection(connection, sessionState.sessionId);
23605
23626
  }
23606
23627
  getFailure() {
23607
23628
  return this.failure;
@@ -23612,12 +23633,32 @@ var CodexEventHandler = class {
23612
23633
  return plan;
23613
23634
  }
23614
23635
  async handleNotification(notification) {
23615
- const session = new ACPSessionConnection(this.connection, this.sessionState.sessionId);
23616
23636
  const updateEvent = await this.createUpdateEvent(notification);
23617
23637
  if (updateEvent) {
23618
- await session.update(updateEvent);
23638
+ await this.session.update(updateEvent);
23619
23639
  }
23620
23640
  }
23641
+ async flushPendingPlanUpdates() {
23642
+ this.cancelPlanUpdateTimer();
23643
+ do {
23644
+ const itemIds = [...this.pendingPlanItemIds];
23645
+ this.pendingPlanItemIds.clear();
23646
+ await Promise.all(itemIds.map((itemId) => {
23647
+ const text = this.planDeltaTextByItemId.get(itemId) ?? "";
23648
+ return text.length > 0 ? this.enqueuePlanSnapshot(itemId, text) : Promise.resolve();
23649
+ }));
23650
+ await this.planUpdateChain;
23651
+ } while (this.pendingPlanItemIds.size > 0);
23652
+ }
23653
+ async dispose() {
23654
+ if (this.disposed) return;
23655
+ await this.flushPendingPlanUpdates();
23656
+ this.disposed = true;
23657
+ this.cancelPlanUpdateTimer();
23658
+ this.pendingPlanItemIds.clear();
23659
+ this.planDeltaTextByItemId.clear();
23660
+ this.lastEmittedPlanTextByItemId.clear();
23661
+ }
23621
23662
  async createUpdateEvent(notification) {
23622
23663
  switch (notification.method) {
23623
23664
  case "item/agentMessage/delta":
@@ -23636,6 +23677,8 @@ var CodexEventHandler = class {
23636
23677
  this.sessionState.currentTurnId = notification.params.turn.id;
23637
23678
  return null;
23638
23679
  case "turn/completed":
23680
+ await this.flushPendingPlanUpdates();
23681
+ this.clearPlanTurnState();
23639
23682
  this.sessionState.currentTurnId = null;
23640
23683
  return null;
23641
23684
  case "thread/tokenUsage/updated":
@@ -23781,9 +23824,7 @@ ${event.details}` : "";
23781
23824
  return null;
23782
23825
  }
23783
23826
  this.sessionState.currentGoal = goalSnapshot;
23784
- return this.createCodexSessionInfoUpdate({
23785
- goal: goalSnapshot
23786
- });
23827
+ return this.createGoalSessionInfoUpdate(goalSnapshot);
23787
23828
  }
23788
23829
  createThreadGoalClearedEvent(_event) {
23789
23830
  this.sessionState.goalRevision += 1;
@@ -23791,9 +23832,13 @@ ${event.details}` : "";
23791
23832
  return null;
23792
23833
  }
23793
23834
  this.sessionState.currentGoal = null;
23794
- return this.createCodexSessionInfoUpdate({
23795
- goal: null
23796
- });
23835
+ return this.createGoalSessionInfoUpdate(null);
23836
+ }
23837
+ createGoalSessionInfoUpdate(goal) {
23838
+ return {
23839
+ sessionUpdate: "session_info_update",
23840
+ _meta: { goal }
23841
+ };
23797
23842
  }
23798
23843
  createReasoningDeltaEvent(event) {
23799
23844
  this.seenReasoningDeltaItemIds.add(event.itemId);
@@ -23806,7 +23851,11 @@ ${event.details}` : "";
23806
23851
  const text = this.planDeltaTextByItemId.get(event.itemId) ?? "";
23807
23852
  const updatedText = text + event.delta;
23808
23853
  this.planDeltaTextByItemId.set(event.itemId, updatedText);
23809
- return this.supportsPlanUpdates ? this.createPlanUpdateEvent(updatedText, event.itemId) : null;
23854
+ if (this.supportsPlanUpdates) {
23855
+ this.pendingPlanItemIds.add(event.itemId);
23856
+ this.schedulePlanUpdate();
23857
+ }
23858
+ return null;
23810
23859
  }
23811
23860
  createReasoningSectionBreakEvent(event) {
23812
23861
  this.seenReasoningDeltaItemIds.add(event.itemId);
@@ -23903,8 +23952,7 @@ ${event.details}` : "";
23903
23952
  return null;
23904
23953
  case "plan": {
23905
23954
  const deltaText = this.planDeltaTextByItemId.get(event.item.id) ?? "";
23906
- this.planDeltaTextByItemId.delete(event.item.id);
23907
- return this.createCompletedPlanEvent(event.item, deltaText);
23955
+ return await this.createCompletedPlanEvent(event.item, deltaText);
23908
23956
  }
23909
23957
  case "exitedReviewMode":
23910
23958
  return this.createExitedReviewModeEvent(event.item);
@@ -23933,13 +23981,53 @@ ${event.details}` : "";
23933
23981
  }
23934
23982
  return this.createAgentThoughtEvent(text, item.id);
23935
23983
  }
23936
- createCompletedPlanEvent(item, deltaText) {
23984
+ async createCompletedPlanEvent(item, deltaText) {
23937
23985
  const text = item.text.length > 0 ? item.text : deltaText;
23986
+ this.pendingPlanItemIds.delete(item.id);
23987
+ if (this.pendingPlanItemIds.size === 0) {
23988
+ this.cancelPlanUpdateTimer();
23989
+ }
23990
+ this.planDeltaTextByItemId.delete(item.id);
23938
23991
  if (text.length === 0) {
23939
23992
  return null;
23940
23993
  }
23941
23994
  this.completedPlan = { itemId: item.id, text };
23942
- return this.supportsPlanUpdates ? this.createPlanUpdateEvent(text, item.id) : this.createPlanTextEvent(text, item.id);
23995
+ if (this.supportsPlanUpdates) {
23996
+ await this.enqueuePlanSnapshot(item.id, text);
23997
+ return null;
23998
+ }
23999
+ return this.createPlanTextEvent(text, item.id);
24000
+ }
24001
+ schedulePlanUpdate() {
24002
+ if (this.disposed || this.planUpdateTimer !== null) return;
24003
+ this.planUpdateTimer = setTimeout(() => {
24004
+ this.planUpdateTimer = null;
24005
+ void this.flushPendingPlanUpdates().catch((error51) => {
24006
+ logger.error("Failed to flush throttled plan updates", error51);
24007
+ });
24008
+ }, _CodexEventHandler.PLAN_UPDATE_INTERVAL_MS);
24009
+ }
24010
+ cancelPlanUpdateTimer() {
24011
+ if (this.planUpdateTimer === null) return;
24012
+ clearTimeout(this.planUpdateTimer);
24013
+ this.planUpdateTimer = null;
24014
+ }
24015
+ enqueuePlanSnapshot(itemId, text) {
24016
+ const send = async () => {
24017
+ if (this.lastEmittedPlanTextByItemId.get(itemId) === text) return;
24018
+ await this.session.update(this.createPlanUpdateEvent(text, itemId));
24019
+ this.lastEmittedPlanTextByItemId.set(itemId, text);
24020
+ };
24021
+ const result = this.planUpdateChain.then(send);
24022
+ this.planUpdateChain = result.catch(() => {
24023
+ });
24024
+ return result;
24025
+ }
24026
+ clearPlanTurnState() {
24027
+ this.cancelPlanUpdateTimer();
24028
+ this.pendingPlanItemIds.clear();
24029
+ this.planDeltaTextByItemId.clear();
24030
+ this.lastEmittedPlanTextByItemId.clear();
23943
24031
  }
23944
24032
  createPlanUpdateEvent(text, planId) {
23945
24033
  return {
@@ -25279,6 +25367,11 @@ var ChatGptAuthMethod = {
25279
25367
  name: "ChatGPT",
25280
25368
  description: "Use ChatGPT to authenticate"
25281
25369
  };
25370
+ var ChatGptDeviceCodeAuthMethod = {
25371
+ id: "chat-gpt-device-code",
25372
+ name: "ChatGPT (device code)",
25373
+ description: "Sign in to ChatGPT by opening a verification page and entering a one-time code"
25374
+ };
25282
25375
  var GatewayAuthMethod = {
25283
25376
  id: "gateway",
25284
25377
  name: "Custom model gateway",
@@ -25295,6 +25388,9 @@ function getCodexAuthMethods(clientCapabilities, env = process.env) {
25295
25388
  if (!env["NO_BROWSER"]) {
25296
25389
  authMethods.push(ChatGptAuthMethod);
25297
25390
  }
25391
+ if (clientSupportsUrlElicitation(clientCapabilities)) {
25392
+ authMethods.push(ChatGptDeviceCodeAuthMethod);
25393
+ }
25298
25394
  const supportsGatewayAuth = clientCapabilities?.auth?._meta?.["gateway"] === true;
25299
25395
  if (supportsGatewayAuth) {
25300
25396
  authMethods.push(GatewayAuthMethod);
@@ -25302,7 +25398,7 @@ function getCodexAuthMethods(clientCapabilities, env = process.env) {
25302
25398
  return authMethods;
25303
25399
  }
25304
25400
  function isCodexAuthRequest(request) {
25305
- return request.methodId === "api-key" || request.methodId === "chat-gpt" || request.methodId === "gateway";
25401
+ return request.methodId === "api-key" || request.methodId === "chat-gpt" || request.methodId === "chat-gpt-device-code" || request.methodId === "gateway";
25306
25402
  }
25307
25403
 
25308
25404
  // node_modules/open/index.js
@@ -26065,7 +26161,7 @@ var package_default = {
26065
26161
  publishConfig: {
26066
26162
  access: "public"
26067
26163
  },
26068
- version: "1.1.8",
26164
+ version: "1.1.10",
26069
26165
  description: "",
26070
26166
  main: "dist/index.js",
26071
26167
  bin: {
@@ -26126,7 +26222,7 @@ var package_default = {
26126
26222
  },
26127
26223
  dependencies: {
26128
26224
  "@agentclientprotocol/sdk": "^1.3.0",
26129
- "@openai/codex": "^0.145.0",
26225
+ "@openai/codex": "^0.146.1",
26130
26226
  diff: "^9.0.0",
26131
26227
  open: "^11.0.0",
26132
26228
  "vscode-jsonrpc": "^9.0.1",
@@ -26212,43 +26308,24 @@ var CodexAcpClient = class {
26212
26308
  getHomePath() {
26213
26309
  return this.configPath;
26214
26310
  }
26215
- async authenticate(authRequest) {
26311
+ async authenticate(authRequest, urlElicitationRequester) {
26216
26312
  if (!isCodexAuthRequest(authRequest)) {
26217
26313
  throw RequestError.invalidRequest();
26218
26314
  }
26219
26315
  this.gatewayConfig = null;
26220
26316
  switch (authRequest.methodId) {
26221
- case "api-key": {
26222
- const apiKey = authRequest._meta?.["api-key"]?.apiKey ?? this.readApiKeyFromEnv();
26223
- return await this.authenticateWithApiKey(apiKey);
26224
- }
26225
- case "chat-gpt": {
26226
- const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
26227
- if (accountResponse.account?.type === "chatgpt") {
26228
- return true;
26229
- }
26230
- const loginCompletedPromise = this.awaitNextLoginCompleted();
26231
- const loginResponse = await this.codexClient.accountLogin({ type: "chatgpt" });
26232
- if (loginResponse.type == "chatgpt") {
26233
- await open_default(loginResponse.authUrl);
26234
- }
26235
- const result = await loginCompletedPromise;
26236
- return result.success;
26237
- }
26317
+ case "api-key":
26318
+ return await this.authenticateWithApiKey(authRequest);
26319
+ case "chat-gpt":
26320
+ return await this.authenticateWithChatGpt();
26321
+ case "chat-gpt-device-code":
26322
+ return await this.authenticateWithChatGptDeviceCode(urlElicitationRequester);
26238
26323
  case "gateway":
26239
- if (!authRequest._meta) throw RequestError.invalidRequest();
26240
- const gatewaySettings = authRequest._meta["gateway"];
26241
- if (!gatewaySettings) throw RequestError.invalidRequest();
26242
- this.applyGatewayConfig({
26243
- baseUrl: gatewaySettings.baseUrl,
26244
- apiType: GatewayAuthMethod._meta.gateway.protocol,
26245
- headers: gatewaySettings.headers,
26246
- providerName: gatewaySettings.providerName
26247
- });
26248
- return true;
26324
+ return this.authenticateWithGateway(authRequest);
26249
26325
  }
26250
26326
  }
26251
- async authenticateWithApiKey(apiKey) {
26327
+ async authenticateWithApiKey(authRequest) {
26328
+ const apiKey = authRequest._meta?.["api-key"]?.apiKey ?? this.readApiKeyFromEnv();
26252
26329
  const loginCompletedPromise = this.awaitNextLoginCompleted();
26253
26330
  await this.codexClient.accountLogin({
26254
26331
  type: "apiKey",
@@ -26257,6 +26334,56 @@ var CodexAcpClient = class {
26257
26334
  const result = await loginCompletedPromise;
26258
26335
  return result.success;
26259
26336
  }
26337
+ async authenticateWithChatGpt() {
26338
+ const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
26339
+ if (accountResponse.account?.type === "chatgpt") {
26340
+ return true;
26341
+ }
26342
+ const loginCompletedPromise = this.awaitNextLoginCompleted();
26343
+ const loginResponse = await this.codexClient.accountLogin({ type: "chatgpt" });
26344
+ if (loginResponse.type == "chatgpt") {
26345
+ await open_default(loginResponse.authUrl);
26346
+ }
26347
+ const result = await loginCompletedPromise;
26348
+ return result.success;
26349
+ }
26350
+ async authenticateWithChatGptDeviceCode(urlElicitationRequester) {
26351
+ const accountResponse = await this.codexClient.accountRead({ refreshToken: true });
26352
+ if (accountResponse.account?.type === "chatgpt") {
26353
+ return true;
26354
+ }
26355
+ if (!urlElicitationRequester) {
26356
+ throw RequestError.invalidRequest(void 0, "Device code authentication requires URL elicitation support");
26357
+ }
26358
+ const loginCompletedPromise = this.awaitNextLoginCompleted();
26359
+ const loginResponse = await this.codexClient.accountLogin({ type: "chatgptDeviceCode" });
26360
+ if (loginResponse.type !== "chatgptDeviceCode") {
26361
+ return false;
26362
+ }
26363
+ const elicitationResponse = await urlElicitationRequester.elicitUrl({
26364
+ url: loginResponse.verificationUrl,
26365
+ message: `Sign in to ChatGPT and enter this code: ${loginResponse.userCode}`,
26366
+ elicitationId: loginResponse.loginId
26367
+ });
26368
+ if (!CreateElicitationResponse.isAccept(elicitationResponse)) {
26369
+ await this.codexClient.accountLoginCancel({ loginId: loginResponse.loginId });
26370
+ return false;
26371
+ }
26372
+ const result = await loginCompletedPromise;
26373
+ return result.success;
26374
+ }
26375
+ authenticateWithGateway(authRequest) {
26376
+ if (!authRequest._meta) throw RequestError.invalidRequest();
26377
+ const gatewaySettings = authRequest._meta["gateway"];
26378
+ if (!gatewaySettings) throw RequestError.invalidRequest();
26379
+ this.applyGatewayConfig({
26380
+ baseUrl: gatewaySettings.baseUrl,
26381
+ apiType: GatewayAuthMethod._meta.gateway.protocol,
26382
+ headers: gatewaySettings.headers,
26383
+ providerName: gatewaySettings.providerName
26384
+ });
26385
+ return true;
26386
+ }
26260
26387
  readApiKeyFromEnv() {
26261
26388
  for (const envVar of [CODEX_API_KEY_ENV_VAR, OPENAI_API_KEY_ENV_VAR]) {
26262
26389
  const value = process.env[envVar]?.trim();
@@ -28506,6 +28633,13 @@ function numberValue(value) {
28506
28633
  return typeof value === "number" && Number.isFinite(value) ? value : null;
28507
28634
  }
28508
28635
 
28636
+ // src/AcpExtensions.ts
28637
+ var LEGACY_SET_SESSION_MODEL_METHOD = "session/set_model";
28638
+ var SESSION_STEERING_METHOD = "_session/steering";
28639
+ function isExtMethodRequest(request) {
28640
+ 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;
28641
+ }
28642
+
28509
28643
  // src/FastModeConfig.ts
28510
28644
  var FAST_MODE_CONFIG_ID = "fast-mode";
28511
28645
  var FAST_MODE_CATEGORY = "model_config";
@@ -28663,6 +28797,11 @@ var CodexAcpServer = class _CodexAcpServer {
28663
28797
  _meta: {
28664
28798
  steering: {
28665
28799
  supported: true
28800
+ },
28801
+ goal: {
28802
+ version: GOAL_EXTENSION_VERSION,
28803
+ controlMethod: GOAL_CONTROL_METHOD,
28804
+ actions: [...GOAL_CONTROL_ACTIONS]
28666
28805
  }
28667
28806
  }
28668
28807
  };
@@ -28683,7 +28822,8 @@ var CodexAcpServer = class _CodexAcpServer {
28683
28822
  return await this.unstable_setSessionModel(this.parseLegacySetSessionModelParams(methodRequest.params));
28684
28823
  case SESSION_STEERING_METHOD:
28685
28824
  return await this.executeOrQueueSteeringRequest(this.parseSessionSteerParams(methodRequest.params));
28686
- case GOAL_CONTROL_METHOD: {
28825
+ case GOAL_CONTROL_METHOD:
28826
+ case LEGACY_GOAL_CONTROL_METHOD: {
28687
28827
  const sessionState = this.sessions.get(methodRequest.params.sessionId);
28688
28828
  if (!sessionState) {
28689
28829
  throw RequestError.invalidParams(void 0, `Unknown session: ${methodRequest.params.sessionId}`);
@@ -29034,9 +29174,10 @@ Check ${configPath} and project .codex directories, especially their config.toml
29034
29174
  ...this.createSessionConfigOptionsResponse(this.getSessionState(sessionId))
29035
29175
  };
29036
29176
  }
29037
- async authenticate(_params) {
29177
+ async authenticate(_params, requestId) {
29038
29178
  logger.log("Authenticate request received");
29039
- const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(_params));
29179
+ const elicitationRequester = this.createUrlElicitationRequester(requestId);
29180
+ const isAuthenticated = await this.runWithProcessCheck(() => this.codexAcpClient.authenticate(_params, elicitationRequester));
29040
29181
  if (!isAuthenticated) {
29041
29182
  logger.log("Authenticate request failed");
29042
29183
  throw RequestError.invalidParams();
@@ -29045,6 +29186,18 @@ Check ${configPath} and project .codex directories, especially their config.toml
29045
29186
  logger.log("Authenticate request completed");
29046
29187
  return {};
29047
29188
  }
29189
+ createUrlElicitationRequester(requestId) {
29190
+ if (requestId == null || !clientSupportsUrlElicitation(this.clientCapabilities)) {
29191
+ return void 0;
29192
+ }
29193
+ return {
29194
+ elicitUrl: (request) => this.connection.request(methods.client.elicitation.create, {
29195
+ mode: "url",
29196
+ requestId,
29197
+ ...request
29198
+ })
29199
+ };
29200
+ }
29048
29201
  async logout(_params) {
29049
29202
  logger.log("Logout request received");
29050
29203
  await this.runWithProcessCheck(() => this.codexAcpClient.logout());
@@ -29471,9 +29624,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
29471
29624
  await session.update({
29472
29625
  sessionUpdate: "session_info_update",
29473
29626
  _meta: {
29474
- codex: {
29475
- goal: snapshot
29476
- }
29627
+ goal: snapshot
29477
29628
  }
29478
29629
  });
29479
29630
  }
@@ -30035,12 +30186,14 @@ Check ${configPath} and project .codex directories, especially their config.toml
30035
30186
  return pendingTurnStart;
30036
30187
  };
30037
30188
  const disposePromptRequestCancellation = this.observePromptRequestCancellation(signal, sessionState, activePrompt);
30189
+ let eventHandler = null;
30038
30190
  try {
30039
- const eventHandler = new CodexEventHandler(
30191
+ const promptEventHandler = new CodexEventHandler(
30040
30192
  this.connection,
30041
30193
  sessionState,
30042
30194
  clientSupportsPlanUpdates(this.clientCapabilities)
30043
30195
  );
30196
+ eventHandler = promptEventHandler;
30044
30197
  const approvalHandler = new CodexApprovalHandler(this.connection, sessionState, activePrompt.signal);
30045
30198
  const elicitationHandler = new CodexElicitationHandler(
30046
30199
  this.connection,
@@ -30052,7 +30205,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30052
30205
  params.sessionId,
30053
30206
  async (event) => {
30054
30207
  await elicitationHandler.handleNotification(event);
30055
- return eventHandler.handleNotification(event);
30208
+ return promptEventHandler.handleNotification(event);
30056
30209
  },
30057
30210
  approvalHandler,
30058
30211
  elicitationHandler
@@ -30105,7 +30258,6 @@ Check ${configPath} and project .codex directories, especially their config.toml
30105
30258
  logger.log("Prompt handled by a command");
30106
30259
  await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
30107
30260
  if (commandResult.turnCompleted?.turn.status === "interrupted") {
30108
- await this.notifyConversationInterrupted(params.sessionId);
30109
30261
  return this.cancelledPromptResponse(sessionState);
30110
30262
  }
30111
30263
  const error52 = eventHandler.getFailure();
@@ -30177,13 +30329,14 @@ Check ${configPath} and project .codex directories, especially their config.toml
30177
30329
  }
30178
30330
  await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
30179
30331
  if (turnCompleted.turn.status === "interrupted") {
30180
- await this.notifyConversationInterrupted(params.sessionId);
30332
+ await eventHandler.flushPendingPlanUpdates();
30181
30333
  return this.cancelledPromptResponse(sessionState);
30182
30334
  }
30183
30335
  const error51 = eventHandler.getFailure();
30184
30336
  if (error51) {
30185
30337
  throw error51;
30186
30338
  }
30339
+ await eventHandler.flushPendingPlanUpdates();
30187
30340
  const completedPlan = eventHandler.takeCompletedPlan();
30188
30341
  if (completedPlan !== null && sessionState.collaborationMode === PLAN_COLLABORATION_MODE && !this.promptShouldStop(params.sessionId, activePrompt)) {
30189
30342
  const approved = await this.requestPlanImplementationPermission(
@@ -30242,7 +30395,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30242
30395
  }
30243
30396
  await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
30244
30397
  if (turnCompleted.turn.status === "interrupted") {
30245
- await this.notifyConversationInterrupted(params.sessionId);
30398
+ await eventHandler.flushPendingPlanUpdates();
30246
30399
  return this.cancelledPromptResponse(sessionState);
30247
30400
  }
30248
30401
  const implementationError = eventHandler.getFailure();
@@ -30265,6 +30418,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30265
30418
  throw err;
30266
30419
  } finally {
30267
30420
  logger.log("Prompt completed", { sessionId: params.sessionId });
30421
+ await eventHandler?.dispose();
30268
30422
  disposePromptRequestCancellation();
30269
30423
  sessionState.currentTurnId = null;
30270
30424
  const registeredPendingTurnStart = this.pendingTurnStarts.get(params.sessionId);
@@ -30333,15 +30487,6 @@ Check ${configPath} and project .codex directories, especially their config.toml
30333
30487
  _meta: this.buildQuotaMeta(sessionState)
30334
30488
  };
30335
30489
  }
30336
- async notifyConversationInterrupted(sessionId) {
30337
- if (this.sessionIsClosing(sessionId) || !this.sessions.has(sessionId)) {
30338
- return;
30339
- }
30340
- await this.connection.notify(methods.client.session.update, {
30341
- sessionId,
30342
- update: createAgentTextMessageChunk("*Conversation interrupted*")
30343
- });
30344
- }
30345
30490
  buildQuotaMeta(sessionState) {
30346
30491
  const lastTokenUsage = sessionState.lastTokenUsage;
30347
30492
  const modelName = sessionState.currentModelId.replace(/\[.*?]$/, "");
@@ -30859,6 +31004,9 @@ var CodexAppServerClient = class {
30859
31004
  async accountLogin(params) {
30860
31005
  return await this.sendRequest({ method: "account/login/start", params });
30861
31006
  }
31007
+ async accountLoginCancel(params) {
31008
+ return await this.sendRequest({ method: "account/login/cancel", params });
31009
+ }
30862
31010
  async accountLogout() {
30863
31011
  return await this.sendRequest({ method: "account/logout", params: void 0 });
30864
31012
  }
@@ -31459,5 +31607,5 @@ function startAcpServer() {
31459
31607
  codexAcpServer = null;
31460
31608
  }
31461
31609
  });
31462
- }).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);
31610
+ }).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);
31463
31611
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.1.8",
6
+ "version": "1.1.10",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {
@@ -64,7 +64,7 @@
64
64
  },
65
65
  "dependencies": {
66
66
  "@agentclientprotocol/sdk": "^1.3.0",
67
- "@openai/codex": "^0.145.0",
67
+ "@openai/codex": "^0.146.1",
68
68
  "diff": "^9.0.0",
69
69
  "open": "^11.0.0",
70
70
  "vscode-jsonrpc": "^9.0.1",