@agentconnect.md/codex-acp 2.0.0-agentconnect.2 → 2.1.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 (2) hide show
  1. package/dist/index.js +40 -12
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -27419,6 +27419,7 @@ var AIR_RAW_INPUT_RENDERING_KEY = "rawInputRendering";
27419
27419
  var AIR_PLAN_CONTENT_DELTA_KEY = "planContentDelta";
27420
27420
  var AIR_CONTENT_DELTA_KEY = "contentDelta";
27421
27421
  var AIR_SUBAGENT_KEY = "subagent";
27422
+ var AIR_CUSTOM_ANSWER_KEY = "customAnswer";
27422
27423
  var AIR_EXTENSION_VERSION = 1;
27423
27424
  function withAirMeta(meta3, key, value) {
27424
27425
  const root = asRecord(meta3);
@@ -30092,6 +30093,7 @@ var STRING_CODEX_ERROR_CATEGORIES = {
30092
30093
  serverOverloaded: "overloaded",
30093
30094
  cyberPolicy: "policy_denied",
30094
30095
  misalignmentPolicyViolation: "policy_denied",
30096
+ tooManyDenials: "provider_error",
30095
30097
  internalServerError: "internal_error",
30096
30098
  unauthorized: "auth_required",
30097
30099
  badRequest: "bad_request",
@@ -31798,6 +31800,12 @@ function userInputNoteFieldId(questionId, questionIds) {
31798
31800
  }
31799
31801
  return fieldId;
31800
31802
  }
31803
+ function typedChoiceAnswer(value, question) {
31804
+ if (typeof value !== "string" || value === USER_INPUT_OTHER_OPTION) {
31805
+ return void 0;
31806
+ }
31807
+ return question.options?.some((option) => option.label === value) ? void 0 : value;
31808
+ }
31801
31809
  function userInputResponseValue(content, fieldId) {
31802
31810
  const value = content[fieldId];
31803
31811
  if (typeof value === "string" && value.trim() === "") {
@@ -32026,6 +32034,7 @@ var CodexElicitationHandler = class {
32026
32034
  const properties = {};
32027
32035
  const required2 = [];
32028
32036
  const questionIds = new Set(params.questions.map((question) => question.id));
32037
+ const airClient = isAirClient(this.clientCapabilities);
32029
32038
  for (const question of params.questions) {
32030
32039
  const options = question.options ?? [];
32031
32040
  const hasOptions = options.length > 0;
@@ -32050,7 +32059,7 @@ var CodexElicitationHandler = class {
32050
32059
  title: option.label,
32051
32060
  ...option.description ? { description: option.description } : {}
32052
32061
  })),
32053
- ...hasOtherAnswer && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
32062
+ ...hasOtherAnswer && !airClient && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
32054
32063
  const: USER_INPUT_OTHER_OPTION,
32055
32064
  title: USER_INPUT_OTHER_OPTION,
32056
32065
  description: "Provide a different answer in the note field."
@@ -32061,16 +32070,17 @@ var CodexElicitationHandler = class {
32061
32070
  type: "string"
32062
32071
  };
32063
32072
  if (hasOtherAnswer) {
32073
+ const noteMeta = {
32074
+ codex: {
32075
+ questionId: question.id,
32076
+ role: "user_note",
32077
+ isSecret: question.isSecret
32078
+ }
32079
+ };
32064
32080
  properties[userInputNoteFieldId(question.id, questionIds)] = {
32065
32081
  type: "string",
32066
32082
  title: "Additional answer or note",
32067
- _meta: {
32068
- codex: {
32069
- questionId: question.id,
32070
- role: "user_note",
32071
- isSecret: question.isSecret
32072
- }
32073
- }
32083
+ _meta: airClient ? withAirMeta(noteMeta, AIR_CUSTOM_ANSWER_KEY, true) : noteMeta
32074
32084
  };
32075
32085
  }
32076
32086
  }
@@ -32128,13 +32138,18 @@ var CodexElicitationHandler = class {
32128
32138
  const answers = {};
32129
32139
  const content = contentRecord(response.content);
32130
32140
  const questionIds = new Set(params.questions.map((question) => question.id));
32141
+ const airClient = isAirClient(this.clientCapabilities);
32131
32142
  for (const question of params.questions) {
32132
32143
  const answerValues = [];
32144
+ const hasOtherAnswer = question.isOther && question.options != null && question.options.length > 0;
32133
32145
  const value = userInputResponseValue(content, question.id);
32134
- if (value !== void 0) {
32146
+ const typedAnswer = airClient && hasOtherAnswer ? typedChoiceAnswer(value, question) : void 0;
32147
+ if (typedAnswer !== void 0) {
32148
+ answerValues.push(USER_INPUT_OTHER_OPTION, `${USER_INPUT_NOTE_PREFIX}${typedAnswer.trim()}`);
32149
+ } else if (value !== void 0) {
32135
32150
  answerValues.push(...Array.isArray(value) ? value.map(String) : [String(value)]);
32136
32151
  }
32137
- if (question.isOther && question.options != null && question.options.length > 0) {
32152
+ if (hasOtherAnswer) {
32138
32153
  const note = userInputResponseValue(content, userInputNoteFieldId(question.id, questionIds));
32139
32154
  if (note !== void 0) {
32140
32155
  const notes = Array.isArray(note) ? note : [note];
@@ -33088,7 +33103,7 @@ var package_default = {
33088
33103
  publishConfig: {
33089
33104
  access: "public"
33090
33105
  },
33091
- version: "2.0.0-agentconnect.2",
33106
+ version: "2.1.0-agentconnect.1",
33092
33107
  description: "",
33093
33108
  main: "dist/index.js",
33094
33109
  bin: {
@@ -33151,7 +33166,7 @@ var package_default = {
33151
33166
  },
33152
33167
  dependencies: {
33153
33168
  "@agentclientprotocol/sdk": "^1.5.0",
33154
- "@openai/codex": "^0.158.0",
33169
+ "@openai/codex": "^0.159.1",
33155
33170
  diff: "^9.0.0",
33156
33171
  open: "^11.0.1",
33157
33172
  "vscode-jsonrpc": "^9.0.1",
@@ -33462,6 +33477,15 @@ function isNoActiveTurnError(err) {
33462
33477
  function isUnknownThreadError(err) {
33463
33478
  return isMissingRolloutError(err) || isThreadNotLoadedError(err) || isInvalidThreadIdError(err);
33464
33479
  }
33480
+ function isThreadActiveWriterError(err) {
33481
+ return /\bthread \S+ already has an active writer\b/.test(errorText(err));
33482
+ }
33483
+ function threadActiveWriterRequestError(threadId, err) {
33484
+ return RequestError.invalidRequest(
33485
+ { reason: "thread_active_writer", threadId, details: errorText(err) },
33486
+ "This Codex session is in use by another Codex client (the Codex app, the CLI or an IDE extension). Close the session there or quit that client, then try again."
33487
+ );
33488
+ }
33465
33489
 
33466
33490
  // src/PermissionProfileConfig.ts
33467
33491
  var PERMISSION_PROFILE_CONFIG_ENV = "CODEX_ACP_PERMISSION_PROFILE_CONFIG";
@@ -33872,6 +33896,9 @@ var CodexAcpClient = class {
33872
33896
  * so `thread/read` answers for it and gives back the same state resume
33873
33897
  * would have. A thread id Codex has genuinely never seen fails both calls,
33874
33898
  * and the original resume error is what the caller sees.
33899
+ *
33900
+ * A thread that another Codex client has loaded fails with a clear ACP
33901
+ * error instead of the raw Codex message.
33875
33902
  */
33876
33903
  async resumeThread(params) {
33877
33904
  try {
@@ -33887,6 +33914,7 @@ var CodexAcpClient = class {
33887
33914
  collaborationMode: response.collaborationMode?.mode ?? null
33888
33915
  };
33889
33916
  } catch (err) {
33917
+ if (isThreadActiveWriterError(err)) throw threadActiveWriterRequestError(params.threadId, err);
33890
33918
  if (!isMissingRolloutError(err)) throw err;
33891
33919
  let response;
33892
33920
  try {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.0.0-agentconnect.2",
6
+ "version": "2.1.0-agentconnect.1",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {
@@ -66,7 +66,7 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@agentclientprotocol/sdk": "^1.5.0",
69
- "@openai/codex": "^0.158.0",
69
+ "@openai/codex": "^0.159.1",
70
70
  "diff": "^9.0.0",
71
71
  "open": "^11.0.1",
72
72
  "vscode-jsonrpc": "^9.0.1",