@agentconnect.md/codex-acp 2.0.1-agentconnect.1 → 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 +38 -11
  2. package/package.json +1 -1
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);
@@ -31799,6 +31800,12 @@ function userInputNoteFieldId(questionId, questionIds) {
31799
31800
  }
31800
31801
  return fieldId;
31801
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
+ }
31802
31809
  function userInputResponseValue(content, fieldId) {
31803
31810
  const value = content[fieldId];
31804
31811
  if (typeof value === "string" && value.trim() === "") {
@@ -32027,6 +32034,7 @@ var CodexElicitationHandler = class {
32027
32034
  const properties = {};
32028
32035
  const required2 = [];
32029
32036
  const questionIds = new Set(params.questions.map((question) => question.id));
32037
+ const airClient = isAirClient(this.clientCapabilities);
32030
32038
  for (const question of params.questions) {
32031
32039
  const options = question.options ?? [];
32032
32040
  const hasOptions = options.length > 0;
@@ -32051,7 +32059,7 @@ var CodexElicitationHandler = class {
32051
32059
  title: option.label,
32052
32060
  ...option.description ? { description: option.description } : {}
32053
32061
  })),
32054
- ...hasOtherAnswer && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
32062
+ ...hasOtherAnswer && !airClient && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
32055
32063
  const: USER_INPUT_OTHER_OPTION,
32056
32064
  title: USER_INPUT_OTHER_OPTION,
32057
32065
  description: "Provide a different answer in the note field."
@@ -32062,16 +32070,17 @@ var CodexElicitationHandler = class {
32062
32070
  type: "string"
32063
32071
  };
32064
32072
  if (hasOtherAnswer) {
32073
+ const noteMeta = {
32074
+ codex: {
32075
+ questionId: question.id,
32076
+ role: "user_note",
32077
+ isSecret: question.isSecret
32078
+ }
32079
+ };
32065
32080
  properties[userInputNoteFieldId(question.id, questionIds)] = {
32066
32081
  type: "string",
32067
32082
  title: "Additional answer or note",
32068
- _meta: {
32069
- codex: {
32070
- questionId: question.id,
32071
- role: "user_note",
32072
- isSecret: question.isSecret
32073
- }
32074
- }
32083
+ _meta: airClient ? withAirMeta(noteMeta, AIR_CUSTOM_ANSWER_KEY, true) : noteMeta
32075
32084
  };
32076
32085
  }
32077
32086
  }
@@ -32129,13 +32138,18 @@ var CodexElicitationHandler = class {
32129
32138
  const answers = {};
32130
32139
  const content = contentRecord(response.content);
32131
32140
  const questionIds = new Set(params.questions.map((question) => question.id));
32141
+ const airClient = isAirClient(this.clientCapabilities);
32132
32142
  for (const question of params.questions) {
32133
32143
  const answerValues = [];
32144
+ const hasOtherAnswer = question.isOther && question.options != null && question.options.length > 0;
32134
32145
  const value = userInputResponseValue(content, question.id);
32135
- 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) {
32136
32150
  answerValues.push(...Array.isArray(value) ? value.map(String) : [String(value)]);
32137
32151
  }
32138
- if (question.isOther && question.options != null && question.options.length > 0) {
32152
+ if (hasOtherAnswer) {
32139
32153
  const note = userInputResponseValue(content, userInputNoteFieldId(question.id, questionIds));
32140
32154
  if (note !== void 0) {
32141
32155
  const notes = Array.isArray(note) ? note : [note];
@@ -33089,7 +33103,7 @@ var package_default = {
33089
33103
  publishConfig: {
33090
33104
  access: "public"
33091
33105
  },
33092
- version: "2.0.1-agentconnect.1",
33106
+ version: "2.1.0-agentconnect.1",
33093
33107
  description: "",
33094
33108
  main: "dist/index.js",
33095
33109
  bin: {
@@ -33463,6 +33477,15 @@ function isNoActiveTurnError(err) {
33463
33477
  function isUnknownThreadError(err) {
33464
33478
  return isMissingRolloutError(err) || isThreadNotLoadedError(err) || isInvalidThreadIdError(err);
33465
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
+ }
33466
33489
 
33467
33490
  // src/PermissionProfileConfig.ts
33468
33491
  var PERMISSION_PROFILE_CONFIG_ENV = "CODEX_ACP_PERMISSION_PROFILE_CONFIG";
@@ -33873,6 +33896,9 @@ var CodexAcpClient = class {
33873
33896
  * so `thread/read` answers for it and gives back the same state resume
33874
33897
  * would have. A thread id Codex has genuinely never seen fails both calls,
33875
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.
33876
33902
  */
33877
33903
  async resumeThread(params) {
33878
33904
  try {
@@ -33888,6 +33914,7 @@ var CodexAcpClient = class {
33888
33914
  collaborationMode: response.collaborationMode?.mode ?? null
33889
33915
  };
33890
33916
  } catch (err) {
33917
+ if (isThreadActiveWriterError(err)) throw threadActiveWriterRequestError(params.threadId, err);
33891
33918
  if (!isMissingRolloutError(err)) throw err;
33892
33919
  let response;
33893
33920
  try {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.0.1-agentconnect.1",
6
+ "version": "2.1.0-agentconnect.1",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {