@alas-ide/codex-acp 2.5.0-alas.6 → 2.5.0-alas.7

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 +60 -18
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -32121,6 +32121,17 @@ var CODEX_NETWORK_PERMISSION_TITLE = "Allow network access?";
32121
32121
  var CODEX_FILE_CHANGE_PERMISSION_TITLE = "Make edits?";
32122
32122
  var CODEX_ADDITIONAL_PERMISSIONS_TITLE = "Grant permissions?";
32123
32123
  var PERMISSION_PROMPT_META_KEY = "permission_prompt";
32124
+ var NEUTRAL_PERMISSION_PRESENTATION_META_KEY = "permissionPresentation";
32125
+ var NEUTRAL_QUESTION_CUSTOM_ANSWER_META_KEY = "questionCustomAnswer";
32126
+ function neutralPresentationCapability() {
32127
+ return { version: 1 };
32128
+ }
32129
+ function clientRequestsNeutralPresentation(capabilities, key) {
32130
+ const declared = capabilities?._meta?.[key];
32131
+ if (declared === null || typeof declared !== "object" || Array.isArray(declared)) return false;
32132
+ const version2 = declared["version"];
32133
+ return typeof version2 === "number" && Number.isInteger(version2) && version2 >= 1;
32134
+ }
32124
32135
  function requestPermissionMeta(capabilities, title, reason) {
32125
32136
  const description = nonBlank(reason);
32126
32137
  const permission = {
@@ -32130,6 +32141,7 @@ function requestPermissionMeta(capabilities, title, reason) {
32130
32141
  };
32131
32142
  const meta3 = {
32132
32143
  ...airOnlyMeta(capabilities.airClient, AIR_PERMISSION_KEY, permission),
32144
+ ...capabilities.neutralPermissionPresentation ? { [NEUTRAL_PERMISSION_PRESENTATION_META_KEY]: permission } : {},
32133
32145
  ...capabilities.permissionPromptFields ? { [PERMISSION_PROMPT_META_KEY]: permission } : {}
32134
32146
  };
32135
32147
  return Object.keys(meta3).length > 0 ? { _meta: meta3 } : {};
@@ -32141,11 +32153,15 @@ function readPermissionMeta(meta3) {
32141
32153
  if (typeof title !== "string") return void 0;
32142
32154
  return { version: 1, title, ...typeof description === "string" ? { description } : {} };
32143
32155
  }
32144
- function optionPermissionMeta(airClient, description) {
32156
+ function optionPermissionMeta(capabilities, description) {
32145
32157
  const normalized = nonBlank(description);
32146
32158
  if (!normalized) return void 0;
32147
32159
  const permission = { version: 1, description: normalized };
32148
- return airOnlyMeta(airClient, AIR_PERMISSION_KEY, permission);
32160
+ const meta3 = {
32161
+ ...airOnlyMeta(capabilities.airClient, AIR_PERMISSION_KEY, permission),
32162
+ ...capabilities.neutralPermissionPresentation ? { [NEUTRAL_PERMISSION_PRESENTATION_META_KEY]: permission } : {}
32163
+ };
32164
+ return Object.keys(meta3).length > 0 ? meta3 : void 0;
32149
32165
  }
32150
32166
  function nonBlank(value) {
32151
32167
  const normalized = value?.trim();
@@ -35074,7 +35090,9 @@ var ClientCapabilities = class _ClientCapabilities {
35074
35090
  diffPatchFormat: "none",
35075
35091
  sessionFailureFormat: "none",
35076
35092
  agentFileChangeReportFormat: "none",
35077
- permissionPromptFields: false
35093
+ permissionPromptFields: false,
35094
+ neutralPermissionPresentation: false,
35095
+ neutralQuestionCustomAnswer: false
35078
35096
  });
35079
35097
  /** The client declares `_meta.jetbrains.air`. */
35080
35098
  airClient;
@@ -35096,6 +35114,10 @@ var ClientCapabilities = class _ClientCapabilities {
35096
35114
  agentFileChangeReportFormat;
35097
35115
  /** A permission request has its own `title` and `description` (ACP v2). */
35098
35116
  permissionPromptFields;
35117
+ /** The client gets the permission presentation in `_meta.permissionPresentation`. Only ACP v1 reads the opt-in. */
35118
+ neutralPermissionPresentation;
35119
+ /** A question's note field carries `_meta.questionCustomAnswer`. Only ACP v1 reads the opt-in. */
35120
+ neutralQuestionCustomAnswer;
35099
35121
  constructor(values) {
35100
35122
  this.airClient = values.airClient;
35101
35123
  this.airToolCallContract = values.airToolCallContract;
@@ -35109,6 +35131,8 @@ var ClientCapabilities = class _ClientCapabilities {
35109
35131
  this.sessionFailureFormat = values.sessionFailureFormat;
35110
35132
  this.agentFileChangeReportFormat = values.agentFileChangeReportFormat;
35111
35133
  this.permissionPromptFields = values.permissionPromptFields;
35134
+ this.neutralPermissionPresentation = values.neutralPermissionPresentation;
35135
+ this.neutralQuestionCustomAnswer = values.neutralQuestionCustomAnswer;
35112
35136
  }
35113
35137
  static from(capabilities) {
35114
35138
  const airClient = isAirClient(capabilities);
@@ -35133,7 +35157,9 @@ var ClientCapabilities = class _ClientCapabilities {
35133
35157
  sessionFailureFormat: clientRequestsNeutralSessionFailure(capabilities) ? "neutral" : clientSupportsAirCapability(capabilities, AIR_SESSION_FAILURE_KEY) ? "air" : "none",
35134
35158
  // Likewise. The request and the report use the selected form.
35135
35159
  agentFileChangeReportFormat: clientRequestsNeutralAgentFileChangeReport(capabilities) ? "neutral" : clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY) ? "air" : "none",
35136
- permissionPromptFields: false
35160
+ permissionPromptFields: false,
35161
+ neutralPermissionPresentation: clientRequestsNeutralPresentation(capabilities, NEUTRAL_PERMISSION_PRESENTATION_META_KEY),
35162
+ neutralQuestionCustomAnswer: clientRequestsNeutralPresentation(capabilities, NEUTRAL_QUESTION_CUSTOM_ANSWER_META_KEY)
35137
35163
  });
35138
35164
  }
35139
35165
  /**
@@ -35159,7 +35185,10 @@ var ClientCapabilities = class _ClientCapabilities {
35159
35185
  sessionFailureFormat: clientSupportsAirCapability(capabilities, AIR_SESSION_FAILURE_KEY) ? "air" : "none",
35160
35186
  // The client-neutral report is an ACP v1 extension, so v2 ignores its opt-in.
35161
35187
  agentFileChangeReportFormat: clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY) ? "air" : "none",
35162
- permissionPromptFields: true
35188
+ permissionPromptFields: true,
35189
+ // A v2 request has its own title and description, so v2 ignores both client-neutral opt-ins.
35190
+ neutralPermissionPresentation: false,
35191
+ neutralQuestionCustomAnswer: false
35163
35192
  });
35164
35193
  }
35165
35194
  /**
@@ -38937,9 +38966,9 @@ function parsePersistOptions(meta3) {
38937
38966
  function isMcpToolCallApproval(meta3) {
38938
38967
  return isRecord2(meta3) && meta3["codex_approval_kind"] === "mcp_tool_call";
38939
38968
  }
38940
- function buildMcpPermissionOptions(isToolApproval, persistOptions, airClient) {
38969
+ function buildMcpPermissionOptions(isToolApproval, persistOptions, capabilities) {
38941
38970
  const permissionOption2 = (optionId, name, kind, description) => {
38942
- const meta3 = optionPermissionMeta(airClient, description);
38971
+ const meta3 = optionPermissionMeta(capabilities, description);
38943
38972
  return { optionId, name, kind, ...meta3 ? { _meta: meta3 } : {} };
38944
38973
  };
38945
38974
  const options = [permissionOption2(
@@ -39001,7 +39030,7 @@ function buildMcpPermissionRequest(sessionId, params, context, nextStandaloneToo
39001
39030
  options: buildMcpPermissionOptions(
39002
39031
  context.isToolApproval,
39003
39032
  context.persistOptions,
39004
- renderer.capabilities.airClient
39033
+ renderer.capabilities
39005
39034
  )
39006
39035
  },
39007
39036
  correlatedCallId
@@ -39114,7 +39143,7 @@ function userInputResponseValue(content, fieldId) {
39114
39143
  }
39115
39144
  return value;
39116
39145
  }
39117
- function buildUserInputSchema(questions, clientCapabilities, answersRequired) {
39146
+ function buildUserInputSchema(questions, clientCapabilities, answersRequired, neutralCustomAnswer = false) {
39118
39147
  const properties = {};
39119
39148
  const required2 = [];
39120
39149
  const questionIds = new Set(questions.map((question) => question.id));
@@ -39166,7 +39195,10 @@ function buildUserInputSchema(questions, clientCapabilities, answersRequired) {
39166
39195
  properties[userInputNoteFieldId(question.id, questionIds)] = {
39167
39196
  type: "string",
39168
39197
  title: "Additional answer or note",
39169
- _meta: airClient ? withAirMeta({ ...noteMeta, [LEGACY_AIR_CUSTOM_ANSWER_KEY]: true }, AIR_CUSTOM_ANSWER_KEY, true) : noteMeta
39198
+ _meta: {
39199
+ ...airClient ? withAirMeta({ ...noteMeta, [LEGACY_AIR_CUSTOM_ANSWER_KEY]: true }, AIR_CUSTOM_ANSWER_KEY, true) : noteMeta,
39200
+ ...neutralCustomAnswer ? { [NEUTRAL_QUESTION_CUSTOM_ANSWER_META_KEY]: { version: 1, questionId: question.id } } : {}
39201
+ }
39170
39202
  };
39171
39203
  }
39172
39204
  }
@@ -39176,13 +39208,13 @@ function buildUserInputSchema(questions, clientCapabilities, answersRequired) {
39176
39208
  ...answersRequired ? { required: required2 } : {}
39177
39209
  };
39178
39210
  }
39179
- function buildUserInputRequest(params, clientCapabilities) {
39211
+ function buildUserInputRequest(params, clientCapabilities, neutralCustomAnswer) {
39180
39212
  return {
39181
39213
  sessionId: params.threadId,
39182
39214
  toolCallId: params.itemId,
39183
39215
  mode: "form",
39184
39216
  message: "Codex needs your input to continue.",
39185
- requestedSchema: buildUserInputSchema(params.questions, clientCapabilities, true),
39217
+ requestedSchema: buildUserInputSchema(params.questions, clientCapabilities, true, neutralCustomAnswer),
39186
39218
  _meta: {
39187
39219
  codex: {
39188
39220
  autoResolutionMs: params.autoResolutionMs
@@ -39345,7 +39377,7 @@ var CodexElicitationHandler = class {
39345
39377
  return cancellationSignal ? { cancellationSignal } : void 0;
39346
39378
  }
39347
39379
  async requestUserInputElicitation(params) {
39348
- const request = buildUserInputRequest(params, this.clientCapabilities);
39380
+ const request = buildUserInputRequest(params, this.clientCapabilities, this.renderer.capabilities.neutralQuestionCustomAnswer);
39349
39381
  const signal = subagentInteractionSignal(params.threadId, this.cancellationSignal);
39350
39382
  if (params.autoResolutionMs === null) {
39351
39383
  return await withSubagentUserAction(params.threadId, () => this.connection.request(
@@ -40721,7 +40753,7 @@ var package_default = {
40721
40753
  publishConfig: {
40722
40754
  access: "public"
40723
40755
  },
40724
- version: "2.5.0-alas.6",
40756
+ version: "2.5.0-alas.7",
40725
40757
  description: "",
40726
40758
  main: "dist/index.js",
40727
40759
  bin: {
@@ -40799,7 +40831,7 @@ var package_default = {
40799
40831
  alasDownstream: {
40800
40832
  upstreamVersion: "2.5.0",
40801
40833
  upstreamCommit: "34e08970aa324a2be985f5080674d5aa91d7666f",
40802
- sourceCommit: "7c99c083270255f2960fa4cd2da93f72bdf402ad"
40834
+ sourceCommit: "4b88aaf47a9765b7b64a51712cca179fc141fa46"
40803
40835
  }
40804
40836
  };
40805
40837
 
@@ -49257,14 +49289,16 @@ var AsyncQuestionClient = class {
49257
49289
  }
49258
49290
  };
49259
49291
  var AsyncQuestionElicitations = class {
49260
- constructor(sessionId, clientCapabilities, client) {
49292
+ constructor(sessionId, clientCapabilities, client, neutralCustomAnswer = false) {
49261
49293
  this.sessionId = sessionId;
49262
49294
  this.clientCapabilities = clientCapabilities;
49263
49295
  this.client = client;
49296
+ this.neutralCustomAnswer = neutralCustomAnswer;
49264
49297
  }
49265
49298
  sessionId;
49266
49299
  clientCapabilities;
49267
49300
  client;
49301
+ neutralCustomAnswer;
49268
49302
  // The running turns that asked a question, each with the signal that cancels its questions.
49269
49303
  turns = /* @__PURE__ */ new Map();
49270
49304
  /** Asks the questions of a completed async message and cancels them when their turn ends; never waits. */
@@ -49309,7 +49343,7 @@ var AsyncQuestionElicitations = class {
49309
49343
  mode: "form",
49310
49344
  message: "Codex keeps working while you answer. An answer sent after it finishes is not delivered.",
49311
49345
  // Questions are answered independently, as in Codex.
49312
- requestedSchema: buildUserInputSchema(questions, this.clientCapabilities, false),
49346
+ requestedSchema: buildUserInputSchema(questions, this.clientCapabilities, false, this.neutralCustomAnswer),
49313
49347
  _meta: { codex: { delivery: "async" } }
49314
49348
  };
49315
49349
  void this.client.createElicitation(request, turn.signal).then(
@@ -52673,6 +52707,14 @@ var CodexAcpServer = class {
52673
52707
  ...protocolVersion === 1 && this.capabilities.agentFileChangeReportFormat === "neutral" ? {
52674
52708
  [NEUTRAL_AGENT_FILE_CHANGE_REPORT_META_KEY]: neutralAgentFileChangeReportCapability()
52675
52709
  } : {},
52710
+ // The client-neutral presentation contracts, see `docs/air-extensions.md`. `ClientCapabilities.fromV2`
52711
+ // never selects them.
52712
+ ...this.capabilities.neutralPermissionPresentation ? {
52713
+ [NEUTRAL_PERMISSION_PRESENTATION_META_KEY]: neutralPresentationCapability()
52714
+ } : {},
52715
+ ...this.capabilities.neutralQuestionCustomAnswer ? {
52716
+ [NEUTRAL_QUESTION_CUSTOM_ANSWER_META_KEY]: neutralPresentationCapability()
52717
+ } : {},
52676
52718
  // The session index for a client that opted in without AIR, see `docs/air-extensions.md`.
52677
52719
  ...neutralSessionIndex ? {
52678
52720
  [NEUTRAL_SESSION_INDEX_META_KEY]: neutralSessionIndex
@@ -56659,7 +56701,7 @@ You have been logged out. Please try again.`);
56659
56701
  this.connection,
56660
56702
  this.clientCapabilities,
56661
56703
  () => this.codexAcpClient
56662
- ));
56704
+ ), this.capabilities.neutralQuestionCustomAnswer);
56663
56705
  this.asyncQuestions.set(sessionId, questions);
56664
56706
  }
56665
56707
  return questions;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.5.0-alas.6",
6
+ "version": "2.5.0-alas.7",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {
@@ -81,6 +81,6 @@
81
81
  "alasDownstream": {
82
82
  "upstreamVersion": "2.5.0",
83
83
  "upstreamCommit": "34e08970aa324a2be985f5080674d5aa91d7666f",
84
- "sourceCommit": "7c99c083270255f2960fa4cd2da93f72bdf402ad"
84
+ "sourceCommit": "4b88aaf47a9765b7b64a51712cca179fc141fa46"
85
85
  }
86
86
  }