@agentconnect.md/codex-acp 2.0.1-agentconnect.1 → 2.1.1-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.
- package/dist/index.js +140 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7266,7 +7266,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
7266
7266
|
}
|
|
7267
7267
|
return propValues;
|
|
7268
7268
|
});
|
|
7269
|
-
const
|
|
7269
|
+
const isObject3 = isObject;
|
|
7270
7270
|
const catchall = def.catchall;
|
|
7271
7271
|
let value;
|
|
7272
7272
|
const memo2 = globalConfig.memoizer;
|
|
@@ -7274,7 +7274,7 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
7274
7274
|
inst._zod.parse = (payload, ctx) => {
|
|
7275
7275
|
value ?? (value = _normalized.value);
|
|
7276
7276
|
const input2 = payload.value;
|
|
7277
|
-
if (!
|
|
7277
|
+
if (!isObject3(input2)) {
|
|
7278
7278
|
payload.issues.push({
|
|
7279
7279
|
expected: "object",
|
|
7280
7280
|
code: "invalid_type",
|
|
@@ -7410,7 +7410,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7410
7410
|
return doc.compile();
|
|
7411
7411
|
};
|
|
7412
7412
|
let fastpass;
|
|
7413
|
-
const
|
|
7413
|
+
const isObject3 = isObject;
|
|
7414
7414
|
const jit = !globalConfig.jitless;
|
|
7415
7415
|
const allowsEval2 = allowsEval;
|
|
7416
7416
|
const fastEnabled = jit && allowsEval2.value;
|
|
@@ -7419,7 +7419,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
7419
7419
|
inst._zod.parse = (payload, ctx) => {
|
|
7420
7420
|
value ?? (value = _normalized.value);
|
|
7421
7421
|
const input2 = payload.value;
|
|
7422
|
-
if (!
|
|
7422
|
+
if (!isObject3(input2)) {
|
|
7423
7423
|
payload.issues.push({
|
|
7424
7424
|
expected: "object",
|
|
7425
7425
|
code: "invalid_type",
|
|
@@ -27419,6 +27419,8 @@ 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";
|
|
27423
|
+
var LEGACY_AIR_CUSTOM_ANSWER_KEY = "_askUserQuestionCustomAnswer";
|
|
27422
27424
|
var AIR_EXTENSION_VERSION = 1;
|
|
27423
27425
|
function withAirMeta(meta3, key, value) {
|
|
27424
27426
|
const root = asRecord(meta3);
|
|
@@ -30028,6 +30030,34 @@ function createSessionNotice(severity, title, description) {
|
|
|
30028
30030
|
};
|
|
30029
30031
|
}
|
|
30030
30032
|
|
|
30033
|
+
// src/ServiceErrorMessage.ts
|
|
30034
|
+
var SERVICE_ERROR_TYPES = /* @__PURE__ */ new Set([
|
|
30035
|
+
"invalid_request_error",
|
|
30036
|
+
"server_error",
|
|
30037
|
+
"rate_limit_error",
|
|
30038
|
+
"insufficient_quota",
|
|
30039
|
+
"authentication_error",
|
|
30040
|
+
"permission_error",
|
|
30041
|
+
"not_found_error",
|
|
30042
|
+
"conflict_error",
|
|
30043
|
+
"overloaded_error"
|
|
30044
|
+
]);
|
|
30045
|
+
function readableServiceErrorMessage(text) {
|
|
30046
|
+
let value;
|
|
30047
|
+
try {
|
|
30048
|
+
value = JSON.parse(text);
|
|
30049
|
+
} catch {
|
|
30050
|
+
return text;
|
|
30051
|
+
}
|
|
30052
|
+
if (!isObject2(value) || Object.keys(value).some((key) => !["type", "status", "error"].includes(key)) || value["type"] !== "error" || typeof value["status"] !== "number" || !Number.isInteger(value["status"]) || value["status"] < 400 || value["status"] > 599 || !isObject2(value["error"])) return text;
|
|
30053
|
+
const error62 = value["error"];
|
|
30054
|
+
if (Object.keys(error62).some((key) => !["type", "message", "code", "param"].includes(key)) || typeof error62["type"] !== "string" || !SERVICE_ERROR_TYPES.has(error62["type"]) || typeof error62["message"] !== "string" || error62["message"].trim().length === 0 || ["code", "param"].some((key) => key in error62 && error62[key] !== null && typeof error62[key] !== "string")) return text;
|
|
30055
|
+
return error62["message"];
|
|
30056
|
+
}
|
|
30057
|
+
function isObject2(value) {
|
|
30058
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30059
|
+
}
|
|
30060
|
+
|
|
30031
30061
|
// src/CodexEventHandler.ts
|
|
30032
30062
|
var MAX_SESSION_FAILURE_TITLE_LENGTH = 240;
|
|
30033
30063
|
var SESSION_FAILURE_POLICY = {
|
|
@@ -30821,7 +30851,7 @@ ${event.details}` : event.summary;
|
|
|
30821
30851
|
this.createTurnErrorData(params.error)
|
|
30822
30852
|
);
|
|
30823
30853
|
}
|
|
30824
|
-
return createAgentTextMessageChunk(`${params.error.message}
|
|
30854
|
+
return createAgentTextMessageChunk(`${readableServiceErrorMessage(params.error.message)}
|
|
30825
30855
|
|
|
30826
30856
|
`);
|
|
30827
30857
|
}
|
|
@@ -30839,7 +30869,7 @@ ${event.details}` : event.summary;
|
|
|
30839
30869
|
revision: nextSessionFailureRevision(previous, id),
|
|
30840
30870
|
category: policy.category,
|
|
30841
30871
|
severity,
|
|
30842
|
-
title,
|
|
30872
|
+
title: readableServiceErrorMessage(title),
|
|
30843
30873
|
actions: actionsOverride ?? policy.actions
|
|
30844
30874
|
};
|
|
30845
30875
|
this.failuresById.set(id, failure3);
|
|
@@ -30994,6 +31024,58 @@ function toolCallTitle(update) {
|
|
|
30994
31024
|
return update.title;
|
|
30995
31025
|
}
|
|
30996
31026
|
|
|
31027
|
+
// src/DesktopAttachmentHistory.ts
|
|
31028
|
+
import { pathToFileURL } from "node:url";
|
|
31029
|
+
function attachmentFileUri(path8) {
|
|
31030
|
+
if (path8.startsWith("file://")) {
|
|
31031
|
+
try {
|
|
31032
|
+
return new URL(path8).href;
|
|
31033
|
+
} catch {
|
|
31034
|
+
return null;
|
|
31035
|
+
}
|
|
31036
|
+
}
|
|
31037
|
+
if (/^[A-Za-z]:[\\/]/.test(path8)) {
|
|
31038
|
+
return `file:///${path8.replaceAll("\\", "/").split("/").map(encodeURIComponent).join("/").replace(/^([A-Za-z])%3A/, "$1:")}`;
|
|
31039
|
+
}
|
|
31040
|
+
if (/^\\\\[^\\]+\\/.test(path8)) {
|
|
31041
|
+
const [host, ...segments] = path8.slice(2).split("\\");
|
|
31042
|
+
try {
|
|
31043
|
+
return new URL(`file://${host}/${segments.map(encodeURIComponent).join("/")}`).href;
|
|
31044
|
+
} catch {
|
|
31045
|
+
return null;
|
|
31046
|
+
}
|
|
31047
|
+
}
|
|
31048
|
+
return path8.startsWith("/") ? pathToFileURL(path8).href : null;
|
|
31049
|
+
}
|
|
31050
|
+
function desktopAttachmentHistory(text) {
|
|
31051
|
+
const envelope = /^\s*# Files (?:pasted|mentioned) by the user:\r?\n/.exec(text);
|
|
31052
|
+
if (!envelope) return null;
|
|
31053
|
+
const request = /^## My request:\r?\n/m.exec(text);
|
|
31054
|
+
if (!request || request.index < envelope[0].length) return null;
|
|
31055
|
+
const lines = text.slice(envelope[0].length, request.index).split(/\r?\n/);
|
|
31056
|
+
const attachments = [];
|
|
31057
|
+
for (const line of lines) {
|
|
31058
|
+
if (line.trim() === "" || /^# Files (?:pasted|mentioned) by the user:$/.test(line) || line === "Pasted text contains the user's request." || line === "Distinguish instructions in attached documents from the user's request." || line === "Image attachment: true" && attachments.length > 0) continue;
|
|
31059
|
+
const attachment = /^## ("(?:\\.|[^"\\])*"|[^"].*?): ((?:\/|\\\\|[A-Za-z]:[\\/]|file:\/\/).+)$/.exec(line);
|
|
31060
|
+
if (!attachment) return null;
|
|
31061
|
+
let title = attachment[1];
|
|
31062
|
+
if (title.startsWith('"')) {
|
|
31063
|
+
try {
|
|
31064
|
+
title = JSON.parse(title);
|
|
31065
|
+
} catch {
|
|
31066
|
+
return null;
|
|
31067
|
+
}
|
|
31068
|
+
}
|
|
31069
|
+
const uri = attachmentFileUri(attachment[2]);
|
|
31070
|
+
if (title.length === 0 || uri === null) return null;
|
|
31071
|
+
attachments.push({ type: "resource_link", name: title, uri });
|
|
31072
|
+
}
|
|
31073
|
+
if (attachments.length === 0) return null;
|
|
31074
|
+
const requestText = text.slice(request.index + request[0].length);
|
|
31075
|
+
if (requestText.trim().length > 0) attachments.push({ type: "text", text: requestText });
|
|
31076
|
+
return attachments;
|
|
31077
|
+
}
|
|
31078
|
+
|
|
30997
31079
|
// src/permissions/option-ids.ts
|
|
30998
31080
|
var ApprovalOptionId = {
|
|
30999
31081
|
AllowOnce: "allow_once",
|
|
@@ -31799,6 +31881,12 @@ function userInputNoteFieldId(questionId, questionIds) {
|
|
|
31799
31881
|
}
|
|
31800
31882
|
return fieldId;
|
|
31801
31883
|
}
|
|
31884
|
+
function typedChoiceAnswer(value, question) {
|
|
31885
|
+
if (typeof value !== "string" || value === USER_INPUT_OTHER_OPTION) {
|
|
31886
|
+
return void 0;
|
|
31887
|
+
}
|
|
31888
|
+
return question.options?.some((option) => option.label === value) ? void 0 : value;
|
|
31889
|
+
}
|
|
31802
31890
|
function userInputResponseValue(content, fieldId) {
|
|
31803
31891
|
const value = content[fieldId];
|
|
31804
31892
|
if (typeof value === "string" && value.trim() === "") {
|
|
@@ -32027,6 +32115,7 @@ var CodexElicitationHandler = class {
|
|
|
32027
32115
|
const properties = {};
|
|
32028
32116
|
const required2 = [];
|
|
32029
32117
|
const questionIds = new Set(params.questions.map((question) => question.id));
|
|
32118
|
+
const airClient = isAirClient(this.clientCapabilities);
|
|
32030
32119
|
for (const question of params.questions) {
|
|
32031
32120
|
const options = question.options ?? [];
|
|
32032
32121
|
const hasOptions = options.length > 0;
|
|
@@ -32051,7 +32140,7 @@ var CodexElicitationHandler = class {
|
|
|
32051
32140
|
title: option.label,
|
|
32052
32141
|
...option.description ? { description: option.description } : {}
|
|
32053
32142
|
})),
|
|
32054
|
-
...hasOtherAnswer && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
|
|
32143
|
+
...hasOtherAnswer && !airClient && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
|
|
32055
32144
|
const: USER_INPUT_OTHER_OPTION,
|
|
32056
32145
|
title: USER_INPUT_OTHER_OPTION,
|
|
32057
32146
|
description: "Provide a different answer in the note field."
|
|
@@ -32062,16 +32151,17 @@ var CodexElicitationHandler = class {
|
|
|
32062
32151
|
type: "string"
|
|
32063
32152
|
};
|
|
32064
32153
|
if (hasOtherAnswer) {
|
|
32154
|
+
const noteMeta = {
|
|
32155
|
+
codex: {
|
|
32156
|
+
questionId: question.id,
|
|
32157
|
+
role: "user_note",
|
|
32158
|
+
isSecret: question.isSecret
|
|
32159
|
+
}
|
|
32160
|
+
};
|
|
32065
32161
|
properties[userInputNoteFieldId(question.id, questionIds)] = {
|
|
32066
32162
|
type: "string",
|
|
32067
32163
|
title: "Additional answer or note",
|
|
32068
|
-
_meta: {
|
|
32069
|
-
codex: {
|
|
32070
|
-
questionId: question.id,
|
|
32071
|
-
role: "user_note",
|
|
32072
|
-
isSecret: question.isSecret
|
|
32073
|
-
}
|
|
32074
|
-
}
|
|
32164
|
+
_meta: airClient ? withAirMeta({ ...noteMeta, [LEGACY_AIR_CUSTOM_ANSWER_KEY]: true }, AIR_CUSTOM_ANSWER_KEY, true) : noteMeta
|
|
32075
32165
|
};
|
|
32076
32166
|
}
|
|
32077
32167
|
}
|
|
@@ -32129,13 +32219,18 @@ var CodexElicitationHandler = class {
|
|
|
32129
32219
|
const answers = {};
|
|
32130
32220
|
const content = contentRecord(response.content);
|
|
32131
32221
|
const questionIds = new Set(params.questions.map((question) => question.id));
|
|
32222
|
+
const airClient = isAirClient(this.clientCapabilities);
|
|
32132
32223
|
for (const question of params.questions) {
|
|
32133
32224
|
const answerValues = [];
|
|
32225
|
+
const hasOtherAnswer = question.isOther && question.options != null && question.options.length > 0;
|
|
32134
32226
|
const value = userInputResponseValue(content, question.id);
|
|
32135
|
-
|
|
32227
|
+
const typedAnswer = airClient && hasOtherAnswer ? typedChoiceAnswer(value, question) : void 0;
|
|
32228
|
+
if (typedAnswer !== void 0) {
|
|
32229
|
+
answerValues.push(USER_INPUT_OTHER_OPTION, `${USER_INPUT_NOTE_PREFIX}${typedAnswer.trim()}`);
|
|
32230
|
+
} else if (value !== void 0) {
|
|
32136
32231
|
answerValues.push(...Array.isArray(value) ? value.map(String) : [String(value)]);
|
|
32137
32232
|
}
|
|
32138
|
-
if (
|
|
32233
|
+
if (hasOtherAnswer) {
|
|
32139
32234
|
const note = userInputResponseValue(content, userInputNoteFieldId(question.id, questionIds));
|
|
32140
32235
|
if (note !== void 0) {
|
|
32141
32236
|
const notes = Array.isArray(note) ? note : [note];
|
|
@@ -33089,7 +33184,7 @@ var package_default = {
|
|
|
33089
33184
|
publishConfig: {
|
|
33090
33185
|
access: "public"
|
|
33091
33186
|
},
|
|
33092
|
-
version: "2.
|
|
33187
|
+
version: "2.1.1-agentconnect.1",
|
|
33093
33188
|
description: "",
|
|
33094
33189
|
main: "dist/index.js",
|
|
33095
33190
|
bin: {
|
|
@@ -33463,6 +33558,15 @@ function isNoActiveTurnError(err) {
|
|
|
33463
33558
|
function isUnknownThreadError(err) {
|
|
33464
33559
|
return isMissingRolloutError(err) || isThreadNotLoadedError(err) || isInvalidThreadIdError(err);
|
|
33465
33560
|
}
|
|
33561
|
+
function isThreadActiveWriterError(err) {
|
|
33562
|
+
return /\bthread \S+ already has an active writer\b/.test(errorText(err));
|
|
33563
|
+
}
|
|
33564
|
+
function threadActiveWriterRequestError(threadId, err) {
|
|
33565
|
+
return RequestError.invalidRequest(
|
|
33566
|
+
{ reason: "thread_active_writer", threadId, details: errorText(err) },
|
|
33567
|
+
"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."
|
|
33568
|
+
);
|
|
33569
|
+
}
|
|
33466
33570
|
|
|
33467
33571
|
// src/PermissionProfileConfig.ts
|
|
33468
33572
|
var PERMISSION_PROFILE_CONFIG_ENV = "CODEX_ACP_PERMISSION_PROFILE_CONFIG";
|
|
@@ -33873,6 +33977,9 @@ var CodexAcpClient = class {
|
|
|
33873
33977
|
* so `thread/read` answers for it and gives back the same state resume
|
|
33874
33978
|
* would have. A thread id Codex has genuinely never seen fails both calls,
|
|
33875
33979
|
* and the original resume error is what the caller sees.
|
|
33980
|
+
*
|
|
33981
|
+
* A thread that another Codex client has loaded fails with a clear ACP
|
|
33982
|
+
* error instead of the raw Codex message.
|
|
33876
33983
|
*/
|
|
33877
33984
|
async resumeThread(params) {
|
|
33878
33985
|
try {
|
|
@@ -33888,6 +33995,7 @@ var CodexAcpClient = class {
|
|
|
33888
33995
|
collaborationMode: response.collaborationMode?.mode ?? null
|
|
33889
33996
|
};
|
|
33890
33997
|
} catch (err) {
|
|
33998
|
+
if (isThreadActiveWriterError(err)) throw threadActiveWriterRequestError(params.threadId, err);
|
|
33891
33999
|
if (!isMissingRolloutError(err)) throw err;
|
|
33892
34000
|
let response;
|
|
33893
34001
|
try {
|
|
@@ -39136,8 +39244,12 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
39136
39244
|
createUserMessageUpdates(item) {
|
|
39137
39245
|
const updates = [];
|
|
39138
39246
|
const messageId = item.id;
|
|
39139
|
-
|
|
39140
|
-
|
|
39247
|
+
const contentBlocks = item.content.map((input2) => this.userInputToContentBlocks(input2));
|
|
39248
|
+
const attachmentUris = new Set(contentBlocks.flatMap((blocks, index) => item.content[index]?.type === "text" ? blocks.flatMap((block) => block.type === "resource_link" ? [block.uri] : []) : []));
|
|
39249
|
+
for (const [index, input2] of item.content.entries()) {
|
|
39250
|
+
const nativePath = input2.type === "localImage" || input2.type === "localAudio" || input2.type === "mention" ? input2.path : (input2.type === "image" || input2.type === "audio") && "url" in input2 ? input2.url : null;
|
|
39251
|
+
if (nativePath !== null && attachmentUris.has(attachmentFileUri(nativePath) ?? "")) continue;
|
|
39252
|
+
const blocks = contentBlocks[index];
|
|
39141
39253
|
for (const block of blocks) {
|
|
39142
39254
|
updates.push(createUserMessageChunk(block, messageId));
|
|
39143
39255
|
}
|
|
@@ -39178,22 +39290,24 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
39178
39290
|
userInputToContentBlocks(input2) {
|
|
39179
39291
|
switch (input2.type) {
|
|
39180
39292
|
case "text":
|
|
39181
|
-
return input2.text.length > 0 ? [{ type: "text", text: input2.text }] : [];
|
|
39293
|
+
return desktopAttachmentHistory(input2.text) ?? (input2.text.length > 0 ? [{ type: "text", text: input2.text }] : []);
|
|
39182
39294
|
case "image":
|
|
39183
39295
|
return [{
|
|
39184
39296
|
type: "text",
|
|
39185
39297
|
text: "url" in input2 ? this.formatUriAsLink("image", input2.url) : `image:${input2.fileId}`
|
|
39186
39298
|
}];
|
|
39187
|
-
case "localImage":
|
|
39188
|
-
|
|
39189
|
-
|
|
39299
|
+
case "localImage":
|
|
39300
|
+
case "localAudio":
|
|
39301
|
+
case "mention": {
|
|
39302
|
+
const uri = attachmentFileUri(input2.path);
|
|
39303
|
+
const fileName = input2.path.split(/[\\/]/).pop() || input2.type;
|
|
39304
|
+
const name = input2.type === "mention" && input2.name.trim().length > 0 ? input2.name : fileName;
|
|
39305
|
+
return uri !== null ? [{ type: "resource_link", name, uri }] : [{ type: "text", text: this.formatUriAsLink(name, input2.path) }];
|
|
39190
39306
|
}
|
|
39191
39307
|
case "skill":
|
|
39192
39308
|
return [{ type: "text", text: `skill:${input2.name} (${input2.path})` }];
|
|
39193
39309
|
case "audio":
|
|
39194
|
-
|
|
39195
|
-
case "mention":
|
|
39196
|
-
return [];
|
|
39310
|
+
return [{ type: "text", text: this.formatUriAsLink("audio", input2.url) }];
|
|
39197
39311
|
}
|
|
39198
39312
|
}
|
|
39199
39313
|
formatUriAsLink(name, uri) {
|