@agentclientprotocol/codex-acp 1.1.12 → 1.1.14

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 +109 -23
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -23560,7 +23560,7 @@ function createAgentTextThoughtChunk(text, messageId, meta3) {
23560
23560
  var GOAL_EXTENSION_VERSION = 1;
23561
23561
  var GOAL_CONTROL_METHOD = "_session/goal";
23562
23562
  var LEGACY_GOAL_CONTROL_METHOD = "_codex/session/goal_control";
23563
- var GOAL_CONTROL_ACTIONS = ["pause", "resume", "clear"];
23563
+ var GOAL_CONTROL_ACTIONS = ["set", "pause", "resume", "clear"];
23564
23564
 
23565
23565
  // src/ThreadGoalSnapshot.ts
23566
23566
  function toGoalStatus(status) {
@@ -26161,7 +26161,7 @@ var package_default = {
26161
26161
  publishConfig: {
26162
26162
  access: "public"
26163
26163
  },
26164
- version: "1.1.12",
26164
+ version: "1.1.14",
26165
26165
  description: "",
26166
26166
  main: "dist/index.js",
26167
26167
  bin: {
@@ -26222,7 +26222,7 @@ var package_default = {
26222
26222
  },
26223
26223
  dependencies: {
26224
26224
  "@agentclientprotocol/sdk": "^1.3.0",
26225
- "@openai/codex": "^0.146.1",
26225
+ "@openai/codex": "^0.147.0",
26226
26226
  diff: "^9.0.0",
26227
26227
  open: "^11.0.0",
26228
26228
  "vscode-jsonrpc": "^9.0.1",
@@ -26624,12 +26624,16 @@ var CodexAcpClient = class {
26624
26624
  const response = await this.codexClient.threadGoalGet({ threadId: sessionId });
26625
26625
  return response?.goal ?? null;
26626
26626
  }
26627
- async setGoal(sessionId, objective, onTurnStarted) {
26628
- return await this.codexClient.runGoalSet({
26627
+ async setGoal(sessionId, objective, onTurnStarted, onGoalSet) {
26628
+ const params = {
26629
26629
  threadId: sessionId,
26630
26630
  objective,
26631
26631
  status: "active"
26632
- }, onTurnStarted);
26632
+ };
26633
+ if (onGoalSet === void 0) {
26634
+ return await this.codexClient.runGoalSet(params, onTurnStarted);
26635
+ }
26636
+ return await this.codexClient.runGoalSet(params, onTurnStarted, void 0, onGoalSet);
26633
26637
  }
26634
26638
  async setGoalStatus(sessionId, status) {
26635
26639
  let updatedGoal = null;
@@ -26644,11 +26648,15 @@ var CodexAcpClient = class {
26644
26648
  }
26645
26649
  return updatedGoal;
26646
26650
  }
26647
- async resumeGoal(sessionId, onTurnStarted) {
26648
- return await this.codexClient.runGoalSet({
26651
+ async resumeGoal(sessionId, onTurnStarted, onGoalSet) {
26652
+ const params = {
26649
26653
  threadId: sessionId,
26650
26654
  status: "active"
26651
- }, onTurnStarted);
26655
+ };
26656
+ if (onGoalSet === void 0) {
26657
+ return await this.codexClient.runGoalSet(params, onTurnStarted);
26658
+ }
26659
+ return await this.codexClient.runGoalSet(params, onTurnStarted, void 0, onGoalSet);
26652
26660
  }
26653
26661
  async clearGoal(sessionId) {
26654
26662
  await this.codexClient.runGoalClear({ threadId: sessionId });
@@ -27189,6 +27197,10 @@ function createReasoningEffortConfigOption(supportedReasoningEfforts, currentEff
27189
27197
  }
27190
27198
 
27191
27199
  // src/CodexCommands.ts
27200
+ var GOAL_CONTINUATION_PROMPT = [{
27201
+ type: "text",
27202
+ text: "Continue working toward the active goal."
27203
+ }];
27192
27204
  var CodexCommands = class {
27193
27205
  connection;
27194
27206
  codexAcpClient;
@@ -27477,7 +27489,7 @@ var CodexCommands = class {
27477
27489
  }
27478
27490
  createGoalCommandResult(turnCompleted) {
27479
27491
  if (turnCompleted === null) {
27480
- return { handled: true };
27492
+ return { handled: false, prompt: GOAL_CONTINUATION_PROMPT };
27481
27493
  }
27482
27494
  return {
27483
27495
  handled: true,
@@ -28731,6 +28743,7 @@ var CodexAcpServer = class _CodexAcpServer {
28731
28743
  closingSessions;
28732
28744
  sessionGenerations;
28733
28745
  sessionOpenGenerations;
28746
+ goalControlGenerations;
28734
28747
  constructor(connection, codexAcpClient, defaultAuthRequest, getExitCode, getRecentStderr) {
28735
28748
  this.sessions = /* @__PURE__ */ new Map();
28736
28749
  this.pendingMcpStartupSessions = /* @__PURE__ */ new Map();
@@ -28740,6 +28753,7 @@ var CodexAcpServer = class _CodexAcpServer {
28740
28753
  this.closingSessions = /* @__PURE__ */ new Map();
28741
28754
  this.sessionGenerations = /* @__PURE__ */ new Map();
28742
28755
  this.sessionOpenGenerations = /* @__PURE__ */ new Map();
28756
+ this.goalControlGenerations = /* @__PURE__ */ new Map();
28743
28757
  this.connection = connection;
28744
28758
  this.codexAcpClient = codexAcpClient;
28745
28759
  this.defaultAuthRequest = defaultAuthRequest ?? null;
@@ -28829,12 +28843,51 @@ var CodexAcpServer = class _CodexAcpServer {
28829
28843
  throw RequestError.invalidParams(void 0, `Unknown session: ${methodRequest.params.sessionId}`);
28830
28844
  }
28831
28845
  const sessionGeneration = this.getSessionGeneration(sessionState.sessionId);
28832
- if (methodRequest.params.action === "pause" || methodRequest.params.action === "resume") {
28833
- const status = methodRequest.params.action === "pause" ? "paused" : "active";
28834
- const goal = await this.runWithProcessCheck(() => this.codexAcpClient.setGoalStatus(sessionState.sessionId, status));
28846
+ const goalControlGeneration = this.bumpGoalControlGeneration(sessionState.sessionId);
28847
+ if (methodRequest.params.action === "set") {
28848
+ const objective = methodRequest.params.objective;
28849
+ let updatedGoal = null;
28850
+ const turnCompleted = await this.runWithProcessCheck(() => this.codexAcpClient.setGoal(
28851
+ sessionState.sessionId,
28852
+ objective,
28853
+ void 0,
28854
+ (goal) => {
28855
+ updatedGoal = goal;
28856
+ }
28857
+ ));
28858
+ if (turnCompleted === null && updatedGoal !== null) {
28859
+ await this.startGoalContinuationIfCurrent(
28860
+ sessionState,
28861
+ sessionGeneration,
28862
+ goalControlGeneration,
28863
+ updatedGoal
28864
+ );
28865
+ }
28866
+ } else if (methodRequest.params.action === "pause") {
28867
+ const goal = await this.runWithProcessCheck(() => this.codexAcpClient.setGoalStatus(sessionState.sessionId, "paused"));
28835
28868
  if (this.goalPublishIsCurrent(sessionState, sessionGeneration)) {
28836
28869
  await this.publishGoalSnapshot(sessionState, toThreadGoalSnapshot(goal), false);
28837
28870
  }
28871
+ } else if (methodRequest.params.action === "resume") {
28872
+ let updatedGoal = null;
28873
+ const turnCompleted = await this.runWithProcessCheck(() => this.codexAcpClient.resumeGoal(
28874
+ sessionState.sessionId,
28875
+ void 0,
28876
+ (goal) => {
28877
+ updatedGoal = goal;
28878
+ }
28879
+ ));
28880
+ if (updatedGoal !== null && this.goalPublishIsCurrent(sessionState, sessionGeneration)) {
28881
+ await this.publishGoalSnapshot(sessionState, toThreadGoalSnapshot(updatedGoal), false);
28882
+ }
28883
+ if (turnCompleted === null && updatedGoal !== null) {
28884
+ await this.startGoalContinuationIfCurrent(
28885
+ sessionState,
28886
+ sessionGeneration,
28887
+ goalControlGeneration,
28888
+ updatedGoal
28889
+ );
28890
+ }
28838
28891
  } else if (methodRequest.params.action === "clear") {
28839
28892
  await this.runWithProcessCheck(() => this.codexAcpClient.clearGoal(sessionState.sessionId));
28840
28893
  if (this.goalPublishIsCurrent(sessionState, sessionGeneration)) {
@@ -28934,6 +28987,11 @@ Check ${configPath} and project .codex directories, especially their config.toml
28934
28987
  getSessionGeneration(sessionId) {
28935
28988
  return this.sessionGenerations.get(sessionId) ?? 0;
28936
28989
  }
28990
+ bumpGoalControlGeneration(sessionId) {
28991
+ const generation = (this.goalControlGenerations.get(sessionId) ?? 0) + 1;
28992
+ this.goalControlGenerations.set(sessionId, generation);
28993
+ return generation;
28994
+ }
28937
28995
  bumpSessionGeneration(sessionId) {
28938
28996
  const generation = this.getSessionGeneration(sessionId) + 1;
28939
28997
  this.sessionGenerations.set(sessionId, generation);
@@ -29131,6 +29189,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
29131
29189
  this.pendingTurnStarts.delete(params.sessionId);
29132
29190
  this.activePrompts.delete(params.sessionId);
29133
29191
  this.steeringQueues.delete(params.sessionId);
29192
+ this.goalControlGenerations.delete(params.sessionId);
29134
29193
  }
29135
29194
  this.endSessionCloseFence(params.sessionId);
29136
29195
  }
@@ -29488,29 +29547,48 @@ Check ${configPath} and project .codex directories, especially their config.toml
29488
29547
  * fails or is cancelled before the turn starts.
29489
29548
  */
29490
29549
  async startNewTurnFromSteering(params) {
29550
+ await this.startNewTurnFromExternalPrompt(params, "Steering");
29551
+ return { outcome: "startedNewTurn" };
29552
+ }
29553
+ async startGoalContinuationIfCurrent(sessionState, sessionGeneration, goalControlGeneration, expectedGoal) {
29554
+ await this.startNewTurnFromExternalPrompt({
29555
+ sessionId: sessionState.sessionId,
29556
+ prompt: GOAL_CONTINUATION_PROMPT
29557
+ }, "Goal continuation", async () => {
29558
+ if (!this.goalPublishIsCurrent(sessionState, sessionGeneration) || this.goalControlGenerations.get(sessionState.sessionId) !== goalControlGeneration) {
29559
+ return false;
29560
+ }
29561
+ const currentGoal = await this.runWithProcessCheck(() => this.codexAcpClient.getGoal(sessionState.sessionId));
29562
+ return currentGoal?.status === "active" && currentGoal.objective === expectedGoal.objective && currentGoal.createdAt === expectedGoal.createdAt && this.goalControlGenerations.get(sessionState.sessionId) === goalControlGeneration;
29563
+ });
29564
+ }
29565
+ async startNewTurnFromExternalPrompt(params, source, canStart = async () => true) {
29491
29566
  const previousPrompt = this.activePrompts.get(params.sessionId);
29492
29567
  await previousPrompt?.completion;
29493
29568
  if (this.sessionIsClosing(params.sessionId)) {
29494
29569
  throw RequestError.invalidRequest(`Session ${params.sessionId} is closing`);
29495
29570
  }
29571
+ if (!await canStart()) {
29572
+ return false;
29573
+ }
29496
29574
  return await new Promise((resolve, reject) => {
29497
29575
  let turnStarted = false;
29498
29576
  const promptDone = this.prompt(params, void 0, () => {
29499
29577
  turnStarted = true;
29500
- logger.log("Steering session started a new turn", { sessionId: params.sessionId });
29501
- resolve({ outcome: "startedNewTurn" });
29578
+ logger.log(`${source} started a new turn`, { sessionId: params.sessionId });
29579
+ resolve(true);
29502
29580
  });
29503
29581
  promptDone.then(
29504
29582
  (response) => {
29505
29583
  if (!turnStarted && response.stopReason === "cancelled") {
29506
29584
  reject(RequestError.invalidRequest(`Session ${params.sessionId} was cancelled before the steering turn started`));
29507
29585
  } else {
29508
- resolve({ outcome: "startedNewTurn" });
29586
+ resolve(turnStarted);
29509
29587
  }
29510
29588
  },
29511
29589
  (error51) => {
29512
29590
  if (turnStarted) {
29513
- logger.error(`Steering-started prompt for session ${params.sessionId} failed`, error51);
29591
+ logger.error(`${source} prompt for session ${params.sessionId} failed`, error51);
29514
29592
  } else {
29515
29593
  reject(error51);
29516
29594
  }
@@ -30271,6 +30349,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30271
30349
  _meta: this.buildQuotaMeta(sessionState)
30272
30350
  };
30273
30351
  }
30352
+ const effectiveParams = commandResult.prompt === void 0 ? params : { ...params, prompt: commandResult.prompt };
30274
30353
  if (this.sessionIsClosing(params.sessionId)) {
30275
30354
  return this.cancelledPromptResponse(sessionState);
30276
30355
  }
@@ -30283,7 +30362,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30283
30362
  reason: sessionState.account?.type === "apiKey" ? "API key" : "model lacks reasoning"
30284
30363
  });
30285
30364
  }
30286
- if (!sessionState.supportedInputModalities.includes("image") && params.prompt.some((b) => b.type === "image")) {
30365
+ if (!sessionState.supportedInputModalities.includes("image") && effectiveParams.prompt.some((b) => b.type === "image")) {
30287
30366
  throw RequestError.invalidRequest("The current model does not support image input");
30288
30367
  }
30289
30368
  const agentMode = sessionState.agentMode;
@@ -30294,7 +30373,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
30294
30373
  ensurePendingTurnStart();
30295
30374
  const sendPromptPromise = this.runWithProcessCheck(
30296
30375
  () => this.codexAcpClient.sendPrompt(
30297
- params,
30376
+ effectiveParams,
30298
30377
  agentMode,
30299
30378
  modelId,
30300
30379
  serviceTier,
@@ -31532,10 +31611,17 @@ var sessionSteerParamsParser = external_exports.object({
31532
31611
  sessionId: external_exports.string(),
31533
31612
  prompt: external_exports.array(external_exports.any())
31534
31613
  }).passthrough();
31535
- var goalControlParamsParser = external_exports.object({
31536
- sessionId: external_exports.string(),
31537
- action: external_exports.enum(["pause", "resume", "clear"])
31538
- }).passthrough();
31614
+ var goalControlParamsParser = external_exports.discriminatedUnion("action", [
31615
+ external_exports.object({
31616
+ sessionId: external_exports.string(),
31617
+ action: external_exports.literal("set"),
31618
+ objective: external_exports.string().trim().min(1)
31619
+ }).passthrough(),
31620
+ external_exports.object({
31621
+ sessionId: external_exports.string(),
31622
+ action: external_exports.enum(["pause", "resume", "clear"])
31623
+ }).passthrough()
31624
+ ]);
31539
31625
  if (process.argv.includes("--version")) {
31540
31626
  console.log(`${package_default.name} ${package_default.version}`);
31541
31627
  process.exit(0);
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.1.12",
6
+ "version": "1.1.14",
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.146.1",
67
+ "@openai/codex": "^0.147.0",
68
68
  "diff": "^9.0.0",
69
69
  "open": "^11.0.0",
70
70
  "vscode-jsonrpc": "^9.0.1",