@agentclientprotocol/codex-acp 1.2.0 → 1.4.0
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 +849 -161
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3453,9 +3453,9 @@ var require_main = __commonJS({
|
|
|
3453
3453
|
exports.createMessageConnection = createMessageConnection2;
|
|
3454
3454
|
var ril_1 = __importDefault(require_ril());
|
|
3455
3455
|
ril_1.default.install();
|
|
3456
|
-
var
|
|
3456
|
+
var path8 = __importStar(__require("path"));
|
|
3457
3457
|
var os2 = __importStar(__require("os"));
|
|
3458
|
-
var
|
|
3458
|
+
var fs8 = __importStar(__require("fs"));
|
|
3459
3459
|
var crypto_1 = __require("crypto");
|
|
3460
3460
|
var net_1 = __require("net");
|
|
3461
3461
|
var api_1 = require_api();
|
|
@@ -3596,7 +3596,7 @@ var require_main = __commonJS({
|
|
|
3596
3596
|
}
|
|
3597
3597
|
let randomLength = 32;
|
|
3598
3598
|
const fixedLength = "/lsp-.sock".length;
|
|
3599
|
-
const tmpDir =
|
|
3599
|
+
const tmpDir = fs8.realpathSync(XDG_RUNTIME_DIR ?? os2.tmpdir());
|
|
3600
3600
|
const limit = safeIpcPathLengths.get(process.platform);
|
|
3601
3601
|
if (limit !== void 0) {
|
|
3602
3602
|
randomLength = Math.min(limit - tmpDir.length - fixedLength, randomLength);
|
|
@@ -3605,7 +3605,7 @@ var require_main = __commonJS({
|
|
|
3605
3605
|
throw new Error(`Unable to generate a random pipe name with ${randomLength} characters.`);
|
|
3606
3606
|
}
|
|
3607
3607
|
const randomSuffix = (0, crypto_1.randomBytes)(Math.floor(randomLength / 2)).toString("hex");
|
|
3608
|
-
return
|
|
3608
|
+
return path8.join(tmpDir, `lsp-${randomSuffix}.sock`);
|
|
3609
3609
|
}
|
|
3610
3610
|
function createClientPipeTransport(pipeName, encoding = "utf-8") {
|
|
3611
3611
|
let connectResolve;
|
|
@@ -4509,10 +4509,10 @@ function mergeDefs(...defs) {
|
|
|
4509
4509
|
function cloneDef(schema) {
|
|
4510
4510
|
return mergeDefs(schema._zod.def);
|
|
4511
4511
|
}
|
|
4512
|
-
function getElementAtPath(obj,
|
|
4513
|
-
if (!
|
|
4512
|
+
function getElementAtPath(obj, path8) {
|
|
4513
|
+
if (!path8)
|
|
4514
4514
|
return obj;
|
|
4515
|
-
return
|
|
4515
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
4516
4516
|
}
|
|
4517
4517
|
function promiseAllObject(promisesObj) {
|
|
4518
4518
|
const keys = Object.keys(promisesObj);
|
|
@@ -4921,11 +4921,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
4921
4921
|
}
|
|
4922
4922
|
return false;
|
|
4923
4923
|
}
|
|
4924
|
-
function prefixIssues(
|
|
4924
|
+
function prefixIssues(path8, issues) {
|
|
4925
4925
|
return issues.map((iss) => {
|
|
4926
4926
|
var _a3;
|
|
4927
4927
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
4928
|
-
iss.path.unshift(
|
|
4928
|
+
iss.path.unshift(path8);
|
|
4929
4929
|
return iss;
|
|
4930
4930
|
});
|
|
4931
4931
|
}
|
|
@@ -5072,16 +5072,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
5072
5072
|
}
|
|
5073
5073
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
5074
5074
|
const fieldErrors = { _errors: [] };
|
|
5075
|
-
const processError = (error52,
|
|
5075
|
+
const processError = (error52, path8 = []) => {
|
|
5076
5076
|
for (const issue2 of error52.issues) {
|
|
5077
5077
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5078
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5078
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
5079
5079
|
} else if (issue2.code === "invalid_key") {
|
|
5080
|
-
processError({ issues: issue2.issues }, [...
|
|
5080
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
5081
5081
|
} else if (issue2.code === "invalid_element") {
|
|
5082
|
-
processError({ issues: issue2.issues }, [...
|
|
5082
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
5083
5083
|
} else {
|
|
5084
|
-
const fullpath = [...
|
|
5084
|
+
const fullpath = [...path8, ...issue2.path];
|
|
5085
5085
|
if (fullpath.length === 0) {
|
|
5086
5086
|
fieldErrors._errors.push(mapper(issue2));
|
|
5087
5087
|
} else {
|
|
@@ -5108,17 +5108,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
5108
5108
|
}
|
|
5109
5109
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
5110
5110
|
const result = { errors: [] };
|
|
5111
|
-
const processError = (error52,
|
|
5111
|
+
const processError = (error52, path8 = []) => {
|
|
5112
5112
|
var _a3, _b;
|
|
5113
5113
|
for (const issue2 of error52.issues) {
|
|
5114
5114
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
5115
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
5115
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
5116
5116
|
} else if (issue2.code === "invalid_key") {
|
|
5117
|
-
processError({ issues: issue2.issues }, [...
|
|
5117
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
5118
5118
|
} else if (issue2.code === "invalid_element") {
|
|
5119
|
-
processError({ issues: issue2.issues }, [...
|
|
5119
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
5120
5120
|
} else {
|
|
5121
|
-
const fullpath = [...
|
|
5121
|
+
const fullpath = [...path8, ...issue2.path];
|
|
5122
5122
|
if (fullpath.length === 0) {
|
|
5123
5123
|
result.errors.push(mapper(issue2));
|
|
5124
5124
|
continue;
|
|
@@ -5150,8 +5150,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
5150
5150
|
}
|
|
5151
5151
|
function toDotPath(_path) {
|
|
5152
5152
|
const segs = [];
|
|
5153
|
-
const
|
|
5154
|
-
for (const seg of
|
|
5153
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
5154
|
+
for (const seg of path8) {
|
|
5155
5155
|
if (typeof seg === "number")
|
|
5156
5156
|
segs.push(`[${seg}]`);
|
|
5157
5157
|
else if (typeof seg === "symbol")
|
|
@@ -17843,13 +17843,13 @@ function resolveRef(ref, ctx) {
|
|
|
17843
17843
|
if (!ref.startsWith("#")) {
|
|
17844
17844
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
17845
17845
|
}
|
|
17846
|
-
const
|
|
17847
|
-
if (
|
|
17846
|
+
const path8 = ref.slice(1).split("/").filter(Boolean);
|
|
17847
|
+
if (path8.length === 0) {
|
|
17848
17848
|
return ctx.rootSchema;
|
|
17849
17849
|
}
|
|
17850
17850
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
17851
|
-
if (
|
|
17852
|
-
const key =
|
|
17851
|
+
if (path8[0] === defsKey) {
|
|
17852
|
+
const key = path8[1];
|
|
17853
17853
|
if (!key || !ctx.defs[key]) {
|
|
17854
17854
|
throw new Error(`Reference not found: ${ref}`);
|
|
17855
17855
|
}
|
|
@@ -22777,8 +22777,20 @@ function createTerminalOutputMeta(mode, terminalId, data) {
|
|
|
22777
22777
|
}
|
|
22778
22778
|
}
|
|
22779
22779
|
|
|
22780
|
+
// src/ContextCompactionMeta.ts
|
|
22781
|
+
var CONTEXT_COMPACTION_META_KEY = "contextCompaction";
|
|
22782
|
+
var CONTEXT_COMPACTION_META_VERSION = 1;
|
|
22783
|
+
function createContextCompactionMeta(metadata = {}) {
|
|
22784
|
+
return {
|
|
22785
|
+
[CONTEXT_COMPACTION_META_KEY]: {
|
|
22786
|
+
version: CONTEXT_COMPACTION_META_VERSION,
|
|
22787
|
+
...metadata
|
|
22788
|
+
}
|
|
22789
|
+
};
|
|
22790
|
+
}
|
|
22791
|
+
|
|
22780
22792
|
// src/CodexToolCallMapper.ts
|
|
22781
|
-
var CONTEXT_COMPACTION_META =
|
|
22793
|
+
var CONTEXT_COMPACTION_META = createContextCompactionMeta();
|
|
22782
22794
|
function toAcpStatus(status) {
|
|
22783
22795
|
switch (status) {
|
|
22784
22796
|
case "inProgress":
|
|
@@ -22925,8 +22937,8 @@ function createContextCompactionStartUpdate(item) {
|
|
|
22925
22937
|
return {
|
|
22926
22938
|
sessionUpdate: "tool_call",
|
|
22927
22939
|
toolCallId: item.id,
|
|
22928
|
-
kind: "
|
|
22929
|
-
title: "
|
|
22940
|
+
kind: "think",
|
|
22941
|
+
title: "Compact conversation",
|
|
22930
22942
|
status: "in_progress",
|
|
22931
22943
|
_meta: CONTEXT_COMPACTION_META
|
|
22932
22944
|
};
|
|
@@ -22935,7 +22947,7 @@ function createContextCompactionCompleteUpdate(item) {
|
|
|
22935
22947
|
return {
|
|
22936
22948
|
sessionUpdate: "tool_call_update",
|
|
22937
22949
|
toolCallId: item.id,
|
|
22938
|
-
title: "
|
|
22950
|
+
title: "Compact conversation",
|
|
22939
22951
|
status: "completed",
|
|
22940
22952
|
_meta: CONTEXT_COMPACTION_META
|
|
22941
22953
|
};
|
|
@@ -22944,8 +22956,8 @@ function createCompletedContextCompactionUpdate(item) {
|
|
|
22944
22956
|
return {
|
|
22945
22957
|
sessionUpdate: "tool_call",
|
|
22946
22958
|
toolCallId: item.id,
|
|
22947
|
-
kind: "
|
|
22948
|
-
title: "
|
|
22959
|
+
kind: "think",
|
|
22960
|
+
title: "Compact conversation",
|
|
22949
22961
|
status: "completed",
|
|
22950
22962
|
_meta: CONTEXT_COMPACTION_META
|
|
22951
22963
|
};
|
|
@@ -23235,13 +23247,13 @@ function createTerminalCommandEvent(event, terminalId, cwd) {
|
|
|
23235
23247
|
}
|
|
23236
23248
|
};
|
|
23237
23249
|
}
|
|
23238
|
-
function createSearchTitle(query,
|
|
23239
|
-
if (query &&
|
|
23240
|
-
return `Search for '${query}' in ${
|
|
23250
|
+
function createSearchTitle(query, path8) {
|
|
23251
|
+
if (query && path8) {
|
|
23252
|
+
return `Search for '${query}' in ${path8}`;
|
|
23241
23253
|
} else if (query) {
|
|
23242
23254
|
return `Search for '${query}'`;
|
|
23243
|
-
} else if (
|
|
23244
|
-
return `Search in '${
|
|
23255
|
+
} else if (path8) {
|
|
23256
|
+
return `Search in '${path8}'`;
|
|
23245
23257
|
}
|
|
23246
23258
|
return "Search";
|
|
23247
23259
|
}
|
|
@@ -23467,12 +23479,12 @@ function revertPatch(unifiedDiff) {
|
|
|
23467
23479
|
if (!patch) return null;
|
|
23468
23480
|
return reversePatch(patch);
|
|
23469
23481
|
}
|
|
23470
|
-
function createUpdateDiffContent(
|
|
23482
|
+
function createUpdateDiffContent(path8, oldText, newText) {
|
|
23471
23483
|
return {
|
|
23472
23484
|
type: "diff",
|
|
23473
23485
|
oldText,
|
|
23474
23486
|
newText,
|
|
23475
|
-
path:
|
|
23487
|
+
path: path8,
|
|
23476
23488
|
_meta: {
|
|
23477
23489
|
kind: "update"
|
|
23478
23490
|
}
|
|
@@ -23605,22 +23617,65 @@ var AIR_META_KEY = "air";
|
|
|
23605
23617
|
var AIR_EXTENSION_VERSION_KEY = "version";
|
|
23606
23618
|
var AIR_EXTENSION_CAPABILITIES_KEY = "capabilities";
|
|
23607
23619
|
var AIR_SESSION_FAILURE_KEY = "sessionFailure";
|
|
23620
|
+
var AIR_AGENT_FILE_CHANGE_REPORT_KEY = "agentFileChangeReport";
|
|
23621
|
+
var AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY = "agentFileChangeReportRequest";
|
|
23608
23622
|
var AIR_EXTENSION_VERSION = 1;
|
|
23609
23623
|
|
|
23610
23624
|
// src/CodexEventHandler.ts
|
|
23611
|
-
var
|
|
23612
|
-
|
|
23613
|
-
|
|
23614
|
-
|
|
23615
|
-
|
|
23616
|
-
|
|
23617
|
-
|
|
23618
|
-
|
|
23619
|
-
|
|
23620
|
-
|
|
23621
|
-
|
|
23622
|
-
|
|
23625
|
+
var MAX_SESSION_FAILURE_TITLE_LENGTH = 240;
|
|
23626
|
+
var SESSION_FAILURE_POLICY = {
|
|
23627
|
+
transport_lost: {
|
|
23628
|
+
category: "connection",
|
|
23629
|
+
actions: ["retry", "new_session"]
|
|
23630
|
+
},
|
|
23631
|
+
auth_required: {
|
|
23632
|
+
category: "access",
|
|
23633
|
+
actions: ["login"]
|
|
23634
|
+
},
|
|
23635
|
+
rate_limited: {
|
|
23636
|
+
category: "limit",
|
|
23637
|
+
actions: ["retry"]
|
|
23638
|
+
},
|
|
23639
|
+
quota_exhausted: {
|
|
23640
|
+
category: "limit",
|
|
23641
|
+
actions: []
|
|
23642
|
+
},
|
|
23643
|
+
overloaded: {
|
|
23644
|
+
category: "service",
|
|
23645
|
+
actions: ["retry"]
|
|
23646
|
+
},
|
|
23647
|
+
context_exhausted: {
|
|
23648
|
+
category: "limit",
|
|
23649
|
+
actions: ["new_session"]
|
|
23650
|
+
},
|
|
23651
|
+
budget_exhausted: {
|
|
23652
|
+
category: "limit",
|
|
23653
|
+
actions: ["new_session"]
|
|
23654
|
+
},
|
|
23655
|
+
policy_denied: {
|
|
23656
|
+
category: "request",
|
|
23657
|
+
actions: []
|
|
23658
|
+
},
|
|
23659
|
+
bad_request: {
|
|
23660
|
+
category: "request",
|
|
23661
|
+
actions: []
|
|
23662
|
+
},
|
|
23663
|
+
provider_error: {
|
|
23664
|
+
category: "service",
|
|
23665
|
+
actions: ["retry"]
|
|
23666
|
+
},
|
|
23667
|
+
internal_error: {
|
|
23668
|
+
category: "service",
|
|
23669
|
+
actions: ["retry", "new_session"]
|
|
23670
|
+
}
|
|
23671
|
+
};
|
|
23672
|
+
var SYNTHETIC_FAILURE_TITLE = {
|
|
23673
|
+
transport_lost: "Connection to Codex was lost.",
|
|
23674
|
+
internal_error: "Codex encountered an internal error."
|
|
23623
23675
|
};
|
|
23676
|
+
function nextSessionFailureRevision(previous, id) {
|
|
23677
|
+
return previous?.id === id ? previous.revision + 1 : 1;
|
|
23678
|
+
}
|
|
23624
23679
|
var STRING_CODEX_ERROR_CATEGORIES = {
|
|
23625
23680
|
contextWindowExceeded: "context_exhausted",
|
|
23626
23681
|
sessionBudgetExceeded: "budget_exhausted",
|
|
@@ -23648,6 +23703,12 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23648
23703
|
supportsTypedSessionFailures;
|
|
23649
23704
|
sessionFailureEpoch;
|
|
23650
23705
|
pendingErrors = [];
|
|
23706
|
+
failuresById = /* @__PURE__ */ new Map();
|
|
23707
|
+
activeFailureIdByScope = /* @__PURE__ */ new Map();
|
|
23708
|
+
failureTurnIdById = /* @__PURE__ */ new Map();
|
|
23709
|
+
allocatedFailureScopes = /* @__PURE__ */ new Set();
|
|
23710
|
+
lastSessionNotice;
|
|
23711
|
+
nextNoticeId = 1;
|
|
23651
23712
|
failure = null;
|
|
23652
23713
|
completedPlan = null;
|
|
23653
23714
|
activeFuzzyFileSearchSessions = /* @__PURE__ */ new Set();
|
|
@@ -23672,19 +23733,22 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23672
23733
|
this.supportsTypedSessionFailures = supportsTypedSessionFailures;
|
|
23673
23734
|
this.sessionFailureEpoch = sessionFailureEpoch;
|
|
23674
23735
|
this.session = new ACPSessionConnection(connection, sessionState.sessionId);
|
|
23736
|
+
if (sessionState.sessionFailure !== void 0) {
|
|
23737
|
+
this.failuresById.set(sessionState.sessionFailure.id, sessionState.sessionFailure);
|
|
23738
|
+
}
|
|
23675
23739
|
}
|
|
23676
23740
|
getFailure() {
|
|
23677
23741
|
return this.failure;
|
|
23678
23742
|
}
|
|
23679
23743
|
getTerminalSessionFailureMeta(turnId, allowUnattributed = false) {
|
|
23680
23744
|
const failure = this.sessionState.sessionFailure;
|
|
23681
|
-
if (!this.supportsTypedSessionFailures || failure
|
|
23745
|
+
if (!this.supportsTypedSessionFailures || failure === void 0 || (this.failureTurnIdById.get(failure.id) === void 0 ? !allowUnattributed : turnId === null || this.failureTurnIdById.get(failure.id) !== turnId)) {
|
|
23682
23746
|
return null;
|
|
23683
23747
|
}
|
|
23684
23748
|
return this.createSessionFailureMeta(failure);
|
|
23685
23749
|
}
|
|
23686
|
-
recordSyntheticTerminalFailure(
|
|
23687
|
-
this.recordSessionFailure(
|
|
23750
|
+
recordSyntheticTerminalFailure(kind, turnId) {
|
|
23751
|
+
this.recordSessionFailure(kind, turnId ?? void 0, "error", SYNTHETIC_FAILURE_TITLE[kind]);
|
|
23688
23752
|
}
|
|
23689
23753
|
/**
|
|
23690
23754
|
* Handles notifications after the prompt-local handler has been disposed. The app-server subscription
|
|
@@ -23701,12 +23765,16 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23701
23765
|
return;
|
|
23702
23766
|
}
|
|
23703
23767
|
if (notification.params.willRetry) {
|
|
23704
|
-
await this.session.update(this.
|
|
23768
|
+
await this.session.update(this.createSessionFailureUpdate(this.recordRetryWarning(notification.params, false)));
|
|
23705
23769
|
return;
|
|
23706
23770
|
}
|
|
23707
23771
|
const failure = this.recordSessionFailure(
|
|
23708
|
-
this.
|
|
23709
|
-
|
|
23772
|
+
this.sessionFailureKind(notification.params.error.codexErrorInfo),
|
|
23773
|
+
notification.params.turnId,
|
|
23774
|
+
"error",
|
|
23775
|
+
notification.params.error.message,
|
|
23776
|
+
void 0,
|
|
23777
|
+
false
|
|
23710
23778
|
);
|
|
23711
23779
|
await this.session.update(this.createSessionFailureUpdate(failure));
|
|
23712
23780
|
}
|
|
@@ -23732,21 +23800,19 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23732
23800
|
}
|
|
23733
23801
|
}
|
|
23734
23802
|
async clearSessionFailure() {
|
|
23803
|
+
delete this.sessionState.sessionFailure;
|
|
23804
|
+
}
|
|
23805
|
+
async completeSuccessfulTurn(turnId) {
|
|
23806
|
+
this.lastSessionNotice = void 0;
|
|
23807
|
+
if (!this.supportsTypedSessionFailures || turnId === null) return;
|
|
23735
23808
|
const active = this.sessionState.sessionFailure;
|
|
23736
|
-
if (
|
|
23737
|
-
|
|
23738
|
-
|
|
23739
|
-
const cleared = {
|
|
23740
|
-
...active,
|
|
23741
|
-
revision: active.revision + 1,
|
|
23742
|
-
phase: "cleared"
|
|
23743
|
-
};
|
|
23744
|
-
await this.session.update(this.createSessionFailureUpdate(cleared));
|
|
23745
|
-
this.sessionState.sessionFailure = cleared;
|
|
23809
|
+
if (active?.id !== this.activeFailureIdByScope.get(turnId) || active?.severity !== "warning") return;
|
|
23810
|
+
this.activeFailureIdByScope.delete(turnId);
|
|
23811
|
+
delete this.sessionState.sessionFailure;
|
|
23746
23812
|
}
|
|
23747
23813
|
async handleFailedTurn(turn) {
|
|
23748
23814
|
const activeFailure = this.sessionState.sessionFailure;
|
|
23749
|
-
if (!this.supportsTypedSessionFailures || turn.status !== "failed" || this.failure !== null || activeFailure?.
|
|
23815
|
+
if (!this.supportsTypedSessionFailures || turn.status !== "failed" || this.failure !== null || this.failureTurnIdById.get(activeFailure?.id ?? "") === turn.id && activeFailure?.severity === "error") {
|
|
23750
23816
|
return;
|
|
23751
23817
|
}
|
|
23752
23818
|
const error51 = turn.error ?? {
|
|
@@ -23805,14 +23871,19 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23805
23871
|
async createUpdateEvent(notification) {
|
|
23806
23872
|
switch (notification.method) {
|
|
23807
23873
|
case "item/agentMessage/delta":
|
|
23874
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23808
23875
|
return await this.createTextEvent(notification.params);
|
|
23809
23876
|
case "item/plan/delta":
|
|
23877
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23810
23878
|
return this.createPlanDeltaEvent(notification.params);
|
|
23811
23879
|
case "item/started":
|
|
23880
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23812
23881
|
return await this.createItemEvent(notification.params);
|
|
23813
23882
|
case "item/completed":
|
|
23883
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23814
23884
|
return await this.completeItemEvent(notification.params);
|
|
23815
23885
|
case "turn/plan/updated":
|
|
23886
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23816
23887
|
return await this.updatePlan(notification.params);
|
|
23817
23888
|
case "error":
|
|
23818
23889
|
return await this.createErrorEvent(notification.params);
|
|
@@ -23851,8 +23922,10 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23851
23922
|
closed: true
|
|
23852
23923
|
});
|
|
23853
23924
|
case "item/commandExecution/outputDelta":
|
|
23925
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23854
23926
|
return this.createCommandOutputDeltaEvent(notification.params);
|
|
23855
23927
|
case "item/mcpToolCall/progress":
|
|
23928
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23856
23929
|
return this.createMcpToolProgressEvent(notification.params);
|
|
23857
23930
|
case "account/rateLimits/updated":
|
|
23858
23931
|
this.handleRateLimitsUpdated(notification.params);
|
|
@@ -23863,6 +23936,8 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23863
23936
|
return this.createWarningEvent(notification.params);
|
|
23864
23937
|
case "guardianWarning":
|
|
23865
23938
|
return null;
|
|
23939
|
+
case "deprecationNotice":
|
|
23940
|
+
return this.createDeprecationNoticeEvent(notification.params);
|
|
23866
23941
|
case "item/autoApprovalReview/started":
|
|
23867
23942
|
return this.handleGuardianApprovalReviewStarted(notification.params);
|
|
23868
23943
|
case "item/autoApprovalReview/completed":
|
|
@@ -23870,10 +23945,13 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23870
23945
|
case "thread/compacted":
|
|
23871
23946
|
return this.createContextCompactedEvent();
|
|
23872
23947
|
case "item/reasoning/summaryTextDelta":
|
|
23948
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23873
23949
|
return this.createReasoningDeltaEvent(notification.params);
|
|
23874
23950
|
case "item/reasoning/textDelta":
|
|
23951
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23875
23952
|
return this.createReasoningDeltaEvent(notification.params);
|
|
23876
23953
|
case "item/reasoning/summaryPartAdded":
|
|
23954
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
23877
23955
|
return this.createReasoningSectionBreakEvent(notification.params);
|
|
23878
23956
|
case "model/rerouted":
|
|
23879
23957
|
return this.createModelReroutedEvent(notification.params);
|
|
@@ -23916,7 +23994,6 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23916
23994
|
case "windowsSandbox/setupCompleted":
|
|
23917
23995
|
case "account/login/completed":
|
|
23918
23996
|
case "skills/changed":
|
|
23919
|
-
case "deprecationNotice":
|
|
23920
23997
|
case "mcpServer/oauthLogin/completed":
|
|
23921
23998
|
case "externalAgentConfig/import/completed":
|
|
23922
23999
|
case "rawResponseItem/completed":
|
|
@@ -23944,14 +24021,31 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23944
24021
|
return createAgentTextMessageChunk(event.delta, event.itemId, createCodexMessagePhaseMeta(phase));
|
|
23945
24022
|
}
|
|
23946
24023
|
async createConfigWarningEvent(event) {
|
|
23947
|
-
|
|
24024
|
+
if (this.supportsTypedSessionFailures) {
|
|
24025
|
+
return this.createSessionFailureUpdate(this.recordSessionNotice(...this.sessionNoticeContent(event.summary, event.details)));
|
|
24026
|
+
}
|
|
24027
|
+
const text = event.details ? `${event.summary}
|
|
23948
24028
|
|
|
23949
|
-
${event.details}` :
|
|
23950
|
-
return createAgentTextMessageChunk(`Config warning: ${
|
|
24029
|
+
${event.details}` : event.summary;
|
|
24030
|
+
return createAgentTextMessageChunk(`Config warning: ${text}
|
|
23951
24031
|
|
|
23952
24032
|
`);
|
|
23953
24033
|
}
|
|
24034
|
+
/**
|
|
24035
|
+
* Unlike `warning` and `configWarning`, this notification was dropped outright, so there is no
|
|
24036
|
+
* legacy rendering to preserve. It is surfaced only to clients that negotiated typed records;
|
|
24037
|
+
* every other client keeps seeing exactly what it sees today, which is nothing.
|
|
24038
|
+
*/
|
|
24039
|
+
createDeprecationNoticeEvent(event) {
|
|
24040
|
+
if (!this.supportsTypedSessionFailures) return null;
|
|
24041
|
+
return this.createSessionFailureUpdate(
|
|
24042
|
+
this.recordSessionNotice(...this.sessionNoticeContent(event.summary, event.details))
|
|
24043
|
+
);
|
|
24044
|
+
}
|
|
23954
24045
|
createWarningEvent(event) {
|
|
24046
|
+
if (this.supportsTypedSessionFailures) {
|
|
24047
|
+
return this.createSessionFailureUpdate(this.recordSessionNotice(event.message));
|
|
24048
|
+
}
|
|
23955
24049
|
return createAgentTextMessageChunk(`Warning: ${event.message}
|
|
23956
24050
|
|
|
23957
24051
|
`);
|
|
@@ -24329,7 +24423,13 @@ ${event.stdin}
|
|
|
24329
24423
|
}
|
|
24330
24424
|
if (params.turnId !== this.sessionState.currentTurnId) {
|
|
24331
24425
|
if (this.supportsTypedSessionFailures) {
|
|
24332
|
-
|
|
24426
|
+
const failure = params.willRetry ? this.recordRetryWarning(params) : this.recordSessionFailure(
|
|
24427
|
+
this.sessionFailureKind(params.error.codexErrorInfo),
|
|
24428
|
+
params.turnId,
|
|
24429
|
+
"error",
|
|
24430
|
+
params.error.message
|
|
24431
|
+
);
|
|
24432
|
+
return this.createSessionFailureUpdate(failure);
|
|
24333
24433
|
}
|
|
24334
24434
|
return this.createCodexSessionInfoUpdate({
|
|
24335
24435
|
error: { ...params.error, turnId: params.turnId, willRetry: params.willRetry }
|
|
@@ -24337,7 +24437,7 @@ ${event.stdin}
|
|
|
24337
24437
|
}
|
|
24338
24438
|
if (params.willRetry) {
|
|
24339
24439
|
if (this.supportsTypedSessionFailures) {
|
|
24340
|
-
return this.
|
|
24440
|
+
return this.createSessionFailureUpdate(this.recordRetryWarning(params));
|
|
24341
24441
|
}
|
|
24342
24442
|
return this.createCodexSessionInfoUpdate({
|
|
24343
24443
|
error: {
|
|
@@ -24362,39 +24462,86 @@ ${event.stdin}
|
|
|
24362
24462
|
|
|
24363
24463
|
`);
|
|
24364
24464
|
}
|
|
24365
|
-
createSafeErrorDiagnostic(params) {
|
|
24366
|
-
const category = this.sessionFailureCategory(params.error.codexErrorInfo);
|
|
24367
|
-
return this.createCodexSessionInfoUpdate({
|
|
24368
|
-
error: {
|
|
24369
|
-
category,
|
|
24370
|
-
message: SESSION_FAILURE_PRESENTATION[category].message,
|
|
24371
|
-
turnId: params.turnId,
|
|
24372
|
-
willRetry: params.willRetry
|
|
24373
|
-
}
|
|
24374
|
-
});
|
|
24375
|
-
}
|
|
24376
24465
|
recordTypedSessionFailure(params) {
|
|
24377
|
-
const
|
|
24378
|
-
this.recordSessionFailure(
|
|
24379
|
-
}
|
|
24380
|
-
recordSessionFailure(
|
|
24381
|
-
const
|
|
24382
|
-
const
|
|
24383
|
-
const id =
|
|
24466
|
+
const kind = this.sessionFailureKind(params.error.codexErrorInfo);
|
|
24467
|
+
this.recordSessionFailure(kind, params.turnId, "error", params.error.message);
|
|
24468
|
+
}
|
|
24469
|
+
recordSessionFailure(kind, turnId, severity, title, actionsOverride, attributeToTurn = true) {
|
|
24470
|
+
const policy = SESSION_FAILURE_POLICY[kind];
|
|
24471
|
+
const scope = turnId ?? this.sessionState.sessionId;
|
|
24472
|
+
const id = this.activeFailureIdByScope.get(scope) ?? this.allocateFailureId(scope, turnId);
|
|
24473
|
+
const previous = this.failuresById.get(id);
|
|
24384
24474
|
const failure = {
|
|
24385
24475
|
id,
|
|
24386
|
-
revision: previous
|
|
24387
|
-
|
|
24388
|
-
|
|
24389
|
-
|
|
24390
|
-
|
|
24391
|
-
retryable: presentation.retryable,
|
|
24392
|
-
actions: presentation.actions,
|
|
24393
|
-
...turnId === void 0 ? {} : { turnId }
|
|
24476
|
+
revision: nextSessionFailureRevision(previous, id),
|
|
24477
|
+
category: policy.category,
|
|
24478
|
+
severity,
|
|
24479
|
+
title,
|
|
24480
|
+
actions: actionsOverride ?? policy.actions
|
|
24394
24481
|
};
|
|
24482
|
+
this.failuresById.set(id, failure);
|
|
24483
|
+
this.failureTurnIdById.set(id, attributeToTurn ? turnId : void 0);
|
|
24484
|
+
this.activeFailureIdByScope.set(scope, id);
|
|
24395
24485
|
this.sessionState.sessionFailure = failure;
|
|
24486
|
+
this.lastSessionNotice = void 0;
|
|
24396
24487
|
return failure;
|
|
24397
24488
|
}
|
|
24489
|
+
allocateFailureId(scope, turnId) {
|
|
24490
|
+
if (turnId !== void 0 && !this.allocatedFailureScopes.has(scope)) {
|
|
24491
|
+
this.allocatedFailureScopes.add(scope);
|
|
24492
|
+
return `${turnId}:error`;
|
|
24493
|
+
}
|
|
24494
|
+
this.allocatedFailureScopes.add(scope);
|
|
24495
|
+
return `${scope}:error:${this.sessionFailureEpoch}:${this.nextNoticeId++}`;
|
|
24496
|
+
}
|
|
24497
|
+
/**
|
|
24498
|
+
* A retry warning remains the active incident until Codex produces turn content again. That content is
|
|
24499
|
+
* the only positive signal available from app-server that the turn recovered; a later error then starts
|
|
24500
|
+
* a new incident instead of overwriting the historical reconnect entry. Terminal errors remain active so
|
|
24501
|
+
* duplicate late notifications cannot append duplicate transcript rows.
|
|
24502
|
+
*/
|
|
24503
|
+
completeRetryIncidentOnTurnProgress() {
|
|
24504
|
+
const turnId = this.sessionState.currentTurnId;
|
|
24505
|
+
if (turnId === null) return;
|
|
24506
|
+
const activeId = this.activeFailureIdByScope.get(turnId);
|
|
24507
|
+
if (activeId === void 0 || this.failuresById.get(activeId)?.severity !== "warning") return;
|
|
24508
|
+
this.activeFailureIdByScope.delete(turnId);
|
|
24509
|
+
if (this.sessionState.sessionFailure?.id === activeId) {
|
|
24510
|
+
delete this.sessionState.sessionFailure;
|
|
24511
|
+
}
|
|
24512
|
+
}
|
|
24513
|
+
recordRetryWarning(params, attributeToTurn = true) {
|
|
24514
|
+
const kind = this.sessionFailureKind(params.error.codexErrorInfo);
|
|
24515
|
+
return this.recordSessionFailure(
|
|
24516
|
+
kind,
|
|
24517
|
+
params.turnId,
|
|
24518
|
+
"warning",
|
|
24519
|
+
params.error.message,
|
|
24520
|
+
[],
|
|
24521
|
+
attributeToTurn
|
|
24522
|
+
);
|
|
24523
|
+
}
|
|
24524
|
+
recordSessionNotice(title, details) {
|
|
24525
|
+
const key = `${title}\0${details ?? ""}`;
|
|
24526
|
+
const previous = this.lastSessionNotice?.key === key ? this.lastSessionNotice.failure : void 0;
|
|
24527
|
+
const id = previous?.id ?? `${this.sessionState.sessionId}:notice:${this.sessionFailureEpoch}:${this.nextNoticeId++}`;
|
|
24528
|
+
const notice = {
|
|
24529
|
+
id,
|
|
24530
|
+
revision: nextSessionFailureRevision(previous, id),
|
|
24531
|
+
category: "unknown",
|
|
24532
|
+
severity: "warning",
|
|
24533
|
+
title,
|
|
24534
|
+
...details === void 0 ? {} : { details },
|
|
24535
|
+
actions: []
|
|
24536
|
+
};
|
|
24537
|
+
this.lastSessionNotice = { key, failure: notice };
|
|
24538
|
+
return notice;
|
|
24539
|
+
}
|
|
24540
|
+
sessionNoticeContent(summary, details) {
|
|
24541
|
+
if (details === null) return [summary];
|
|
24542
|
+
const combinedTitle = `${summary} \u2014 ${details}`;
|
|
24543
|
+
return combinedTitle.length <= MAX_SESSION_FAILURE_TITLE_LENGTH ? [combinedTitle] : [summary, details];
|
|
24544
|
+
}
|
|
24398
24545
|
createSessionFailureMeta(failure) {
|
|
24399
24546
|
return {
|
|
24400
24547
|
[JETBRAINS_META_KEY]: {
|
|
@@ -24411,7 +24558,7 @@ ${event.stdin}
|
|
|
24411
24558
|
_meta: this.createSessionFailureMeta(failure)
|
|
24412
24559
|
};
|
|
24413
24560
|
}
|
|
24414
|
-
|
|
24561
|
+
sessionFailureKind(error51) {
|
|
24415
24562
|
if (this.isAuthenticationRequiredError(error51)) return "auth_required";
|
|
24416
24563
|
if (this.getHttpStatusCode(error51) === 429) return "rate_limited";
|
|
24417
24564
|
if (typeof error51 === "string") {
|
|
@@ -24862,11 +25009,11 @@ var CodexApprovalHandler = class {
|
|
|
24862
25009
|
});
|
|
24863
25010
|
}
|
|
24864
25011
|
const fileSystem = permissions.fileSystem;
|
|
24865
|
-
for (const
|
|
24866
|
-
changes.push(this.fileSystemGrantChange(
|
|
25012
|
+
for (const path8 of fileSystem?.read ?? []) {
|
|
25013
|
+
changes.push(this.fileSystemGrantChange(path8, "read", lifetime, suffix));
|
|
24867
25014
|
}
|
|
24868
|
-
for (const
|
|
24869
|
-
changes.push(this.fileSystemGrantChange(
|
|
25015
|
+
for (const path8 of fileSystem?.write ?? []) {
|
|
25016
|
+
changes.push(this.fileSystemGrantChange(path8, "write", lifetime, suffix));
|
|
24870
25017
|
}
|
|
24871
25018
|
for (const entry of fileSystem?.entries ?? []) {
|
|
24872
25019
|
const matcher = (() => {
|
|
@@ -24895,16 +25042,16 @@ var CodexApprovalHandler = class {
|
|
|
24895
25042
|
}
|
|
24896
25043
|
return changes.length > 0 ? { version: 1, changes } : void 0;
|
|
24897
25044
|
}
|
|
24898
|
-
fileSystemGrantChange(
|
|
25045
|
+
fileSystemGrantChange(path8, access, lifetime, suffix) {
|
|
24899
25046
|
return {
|
|
24900
25047
|
type: "grant",
|
|
24901
25048
|
operation: "grant",
|
|
24902
|
-
description: `Allow ${access} access to ${
|
|
25049
|
+
description: `Allow ${access} access to ${path8}${suffix}`,
|
|
24903
25050
|
lifetime,
|
|
24904
25051
|
targets: [{
|
|
24905
25052
|
type: "filesystem",
|
|
24906
25053
|
access: [access],
|
|
24907
|
-
matcher: { type: "exact_path", path:
|
|
25054
|
+
matcher: { type: "exact_path", path: path8 }
|
|
24908
25055
|
}]
|
|
24909
25056
|
};
|
|
24910
25057
|
}
|
|
@@ -25814,15 +25961,15 @@ var wslDefaultBrowser = async () => {
|
|
|
25814
25961
|
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
25815
25962
|
return stdout.trim();
|
|
25816
25963
|
};
|
|
25817
|
-
var convertWslPathToWindows = async (
|
|
25818
|
-
if (/^[a-z]+:\/\//i.test(
|
|
25819
|
-
return
|
|
25964
|
+
var convertWslPathToWindows = async (path8) => {
|
|
25965
|
+
if (/^[a-z]+:\/\//i.test(path8)) {
|
|
25966
|
+
return path8;
|
|
25820
25967
|
}
|
|
25821
25968
|
try {
|
|
25822
|
-
const { stdout } = await execFile2("wslpath", ["-aw",
|
|
25969
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path8], { encoding: "utf8" });
|
|
25823
25970
|
return stdout.trim();
|
|
25824
25971
|
} catch {
|
|
25825
|
-
return
|
|
25972
|
+
return path8;
|
|
25826
25973
|
}
|
|
25827
25974
|
};
|
|
25828
25975
|
|
|
@@ -26372,7 +26519,7 @@ var AgentMode = class _AgentMode {
|
|
|
26372
26519
|
};
|
|
26373
26520
|
|
|
26374
26521
|
// src/CodexAcpClient.ts
|
|
26375
|
-
import
|
|
26522
|
+
import path6 from "node:path";
|
|
26376
26523
|
|
|
26377
26524
|
// src/McpServerName.ts
|
|
26378
26525
|
var MCP_SERVER_NAME_WHITESPACE = /\p{White_Space}/gu;
|
|
@@ -26386,7 +26533,7 @@ var package_default = {
|
|
|
26386
26533
|
publishConfig: {
|
|
26387
26534
|
access: "public"
|
|
26388
26535
|
},
|
|
26389
|
-
version: "1.
|
|
26536
|
+
version: "1.4.0",
|
|
26390
26537
|
description: "",
|
|
26391
26538
|
main: "dist/index.js",
|
|
26392
26539
|
bin: {
|
|
@@ -26539,8 +26686,299 @@ function isRootPath(value) {
|
|
|
26539
26686
|
return value === "/" || /^[A-Za-z]:\/$/.test(value) || /^\/\/[^/]+\/[^/]+\/$/.test(value);
|
|
26540
26687
|
}
|
|
26541
26688
|
|
|
26689
|
+
// src/AgentFileChangeReport.ts
|
|
26690
|
+
import fs7 from "node:fs";
|
|
26691
|
+
import path5 from "node:path";
|
|
26692
|
+
var AGENT_FILE_CHANGE_REPORT_VERSION = 1;
|
|
26693
|
+
var AGENT_FILE_CHANGE_REPORT_TIMEOUT_MS = 3e4;
|
|
26694
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_PATHS = 1024;
|
|
26695
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH = 4096;
|
|
26696
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES = 256 * 1024;
|
|
26697
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_UNCERTAINTY_LENGTH = 2e3;
|
|
26698
|
+
var AGENT_FILE_CHANGE_REPORT_OUTPUT_SCHEMA = {
|
|
26699
|
+
type: "object",
|
|
26700
|
+
additionalProperties: false,
|
|
26701
|
+
required: ["paths", "complete"],
|
|
26702
|
+
properties: {
|
|
26703
|
+
paths: {
|
|
26704
|
+
type: "array",
|
|
26705
|
+
items: { type: "string" }
|
|
26706
|
+
},
|
|
26707
|
+
complete: { type: "boolean" },
|
|
26708
|
+
uncertainty: {
|
|
26709
|
+
type: "string",
|
|
26710
|
+
maxLength: AGENT_FILE_CHANGE_REPORT_MAX_UNCERTAINTY_LENGTH
|
|
26711
|
+
}
|
|
26712
|
+
}
|
|
26713
|
+
};
|
|
26714
|
+
var AGENT_FILE_CHANGE_REPORT_DEVELOPER_INSTRUCTIONS = `You are running an internal, read-only file-change audit for the immediately preceding turn.
|
|
26715
|
+
Do not modify files, run commands that can modify files, or ask the user questions.
|
|
26716
|
+
Report files that the preceding turn causally created, modified, deleted, or moved, including changes made by shell commands, version-control commands, generators, and child processes.
|
|
26717
|
+
Do not report files that were only read or inspected.
|
|
26718
|
+
You may use read-only inspection when needed. If the list may be incomplete, set complete to false and briefly explain why in uncertainty.`;
|
|
26719
|
+
function createAgentFileChangeReportPrompt(workspace) {
|
|
26720
|
+
return `List the paths changed by the immediately preceding turn.
|
|
26721
|
+
Return only the structured result required by the output schema.
|
|
26722
|
+
Relative paths are resolved against the working directory.
|
|
26723
|
+
Working directory: ${JSON.stringify(workspace.cwd)}
|
|
26724
|
+
Additional allowed directories: ${JSON.stringify(workspace.additionalDirectories)}`;
|
|
26725
|
+
}
|
|
26726
|
+
function parseAgentFileChangeReportRequest(meta3) {
|
|
26727
|
+
const jetbrains = asRecord(meta3?.[JETBRAINS_META_KEY]);
|
|
26728
|
+
const air = asRecord(jetbrains?.[AIR_META_KEY]);
|
|
26729
|
+
const request = asRecord(air?.[AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY]);
|
|
26730
|
+
if (request === null || !hasOnlyKeys(request, ["version", "requestId"]) || request["version"] !== AGENT_FILE_CHANGE_REPORT_VERSION) {
|
|
26731
|
+
return null;
|
|
26732
|
+
}
|
|
26733
|
+
const requestId = request["requestId"];
|
|
26734
|
+
if (typeof requestId !== "string" || !/^[A-Za-z0-9._:-]{1,128}$/.test(requestId)) {
|
|
26735
|
+
return null;
|
|
26736
|
+
}
|
|
26737
|
+
return { version: AGENT_FILE_CHANGE_REPORT_VERSION, requestId };
|
|
26738
|
+
}
|
|
26739
|
+
function createReportedAgentFileChangeReport(requestId, turn, workspace) {
|
|
26740
|
+
const modelReport = parseModelFileChangeReport(turn);
|
|
26741
|
+
const normalized = normalizeModelFileChangeReport(modelReport, workspace);
|
|
26742
|
+
return fitReportedAgentFileChangeReport({
|
|
26743
|
+
version: AGENT_FILE_CHANGE_REPORT_VERSION,
|
|
26744
|
+
requestId,
|
|
26745
|
+
status: "reported",
|
|
26746
|
+
...normalized
|
|
26747
|
+
});
|
|
26748
|
+
}
|
|
26749
|
+
function createUnavailableAgentFileChangeReport(requestId, reason) {
|
|
26750
|
+
return {
|
|
26751
|
+
version: AGENT_FILE_CHANGE_REPORT_VERSION,
|
|
26752
|
+
requestId,
|
|
26753
|
+
status: "unavailable",
|
|
26754
|
+
reason
|
|
26755
|
+
};
|
|
26756
|
+
}
|
|
26757
|
+
var AgentFileChangeReportError = class extends Error {
|
|
26758
|
+
reason;
|
|
26759
|
+
constructor(reason, message) {
|
|
26760
|
+
super(message);
|
|
26761
|
+
this.name = "AgentFileChangeReportError";
|
|
26762
|
+
this.reason = reason;
|
|
26763
|
+
}
|
|
26764
|
+
};
|
|
26765
|
+
function parseModelFileChangeReport(turn) {
|
|
26766
|
+
switch (turn.status) {
|
|
26767
|
+
case "interrupted":
|
|
26768
|
+
throw new AgentFileChangeReportError("cancelled", "The audit turn was interrupted");
|
|
26769
|
+
case "failed":
|
|
26770
|
+
throw new AgentFileChangeReportError("providerError", "The audit turn failed");
|
|
26771
|
+
case "inProgress":
|
|
26772
|
+
throw new AgentFileChangeReportError("notReported", "The audit turn did not complete");
|
|
26773
|
+
case "completed":
|
|
26774
|
+
break;
|
|
26775
|
+
}
|
|
26776
|
+
let text = null;
|
|
26777
|
+
for (let index = turn.items.length - 1; index >= 0; index -= 1) {
|
|
26778
|
+
const item = turn.items[index];
|
|
26779
|
+
if (item?.type === "agentMessage") {
|
|
26780
|
+
text = item.text;
|
|
26781
|
+
break;
|
|
26782
|
+
}
|
|
26783
|
+
}
|
|
26784
|
+
if (text === null) {
|
|
26785
|
+
throw new AgentFileChangeReportError("notReported", "The audit turn returned no agent message");
|
|
26786
|
+
}
|
|
26787
|
+
let value;
|
|
26788
|
+
try {
|
|
26789
|
+
value = JSON.parse(text);
|
|
26790
|
+
} catch {
|
|
26791
|
+
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned invalid JSON");
|
|
26792
|
+
}
|
|
26793
|
+
const report = asRecord(value);
|
|
26794
|
+
if (report === null || !hasOnlyKeys(report, ["paths", "complete", "uncertainty"])) {
|
|
26795
|
+
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned an invalid object");
|
|
26796
|
+
}
|
|
26797
|
+
const paths = report["paths"];
|
|
26798
|
+
const complete = report["complete"];
|
|
26799
|
+
const uncertainty = report["uncertainty"];
|
|
26800
|
+
if (!Array.isArray(paths) || !paths.every((item) => typeof item === "string") || typeof complete !== "boolean" || uncertainty !== void 0 && typeof uncertainty !== "string") {
|
|
26801
|
+
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned invalid fields");
|
|
26802
|
+
}
|
|
26803
|
+
const normalizedUncertainty = uncertainty?.trim();
|
|
26804
|
+
if (normalizedUncertainty !== void 0 && normalizedUncertainty.length > AGENT_FILE_CHANGE_REPORT_MAX_UNCERTAINTY_LENGTH) {
|
|
26805
|
+
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned oversized uncertainty");
|
|
26806
|
+
}
|
|
26807
|
+
return {
|
|
26808
|
+
paths,
|
|
26809
|
+
complete,
|
|
26810
|
+
...normalizedUncertainty ? { uncertainty: normalizedUncertainty } : {}
|
|
26811
|
+
};
|
|
26812
|
+
}
|
|
26813
|
+
function fitReportedAgentFileChangeReport(report) {
|
|
26814
|
+
const paths = [...report.paths];
|
|
26815
|
+
let truncated = report.truncated;
|
|
26816
|
+
let fitted = report;
|
|
26817
|
+
while (Buffer.byteLength(JSON.stringify(fitted), "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
|
|
26818
|
+
if (paths.length === 0) {
|
|
26819
|
+
throw new AgentFileChangeReportError("invalidOutput", "The audit report exceeds the wire limit");
|
|
26820
|
+
}
|
|
26821
|
+
paths.pop();
|
|
26822
|
+
truncated = true;
|
|
26823
|
+
fitted = {
|
|
26824
|
+
...report,
|
|
26825
|
+
paths: [...paths],
|
|
26826
|
+
declaredComplete: false,
|
|
26827
|
+
truncated
|
|
26828
|
+
};
|
|
26829
|
+
}
|
|
26830
|
+
return fitted;
|
|
26831
|
+
}
|
|
26832
|
+
function normalizeModelFileChangeReport(report, workspace) {
|
|
26833
|
+
const cwd = normalizeWorkspaceRoot(workspace.cwd);
|
|
26834
|
+
if (cwd === null) {
|
|
26835
|
+
throw new AgentFileChangeReportError("providerError", "The session working directory is not absolute");
|
|
26836
|
+
}
|
|
26837
|
+
const roots = [cwd, ...workspace.additionalDirectories.flatMap((directory) => {
|
|
26838
|
+
const root = normalizeWorkspaceRoot(directory);
|
|
26839
|
+
return root === null || root.flavor !== cwd.flavor ? [] : [root];
|
|
26840
|
+
})];
|
|
26841
|
+
const paths = [];
|
|
26842
|
+
const seen = /* @__PURE__ */ new Set();
|
|
26843
|
+
let totalBytes = 0;
|
|
26844
|
+
let truncated = false;
|
|
26845
|
+
for (const reportedPath of report.paths) {
|
|
26846
|
+
if (reportedPath.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
|
|
26847
|
+
truncated = true;
|
|
26848
|
+
continue;
|
|
26849
|
+
}
|
|
26850
|
+
const normalized = normalizeReportedPath(reportedPath, cwd, roots);
|
|
26851
|
+
if (normalized === null || normalized.value.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
|
|
26852
|
+
truncated = true;
|
|
26853
|
+
continue;
|
|
26854
|
+
}
|
|
26855
|
+
const key = normalized.flavor === "windows" ? normalized.value.toLowerCase() : normalized.value;
|
|
26856
|
+
if (seen.has(key)) {
|
|
26857
|
+
continue;
|
|
26858
|
+
}
|
|
26859
|
+
const bytes = Buffer.byteLength(normalized.value, "utf8");
|
|
26860
|
+
if (paths.length >= AGENT_FILE_CHANGE_REPORT_MAX_PATHS || totalBytes + bytes > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
|
|
26861
|
+
truncated = true;
|
|
26862
|
+
continue;
|
|
26863
|
+
}
|
|
26864
|
+
seen.add(key);
|
|
26865
|
+
paths.push(normalized.value);
|
|
26866
|
+
totalBytes += bytes;
|
|
26867
|
+
}
|
|
26868
|
+
return {
|
|
26869
|
+
paths,
|
|
26870
|
+
declaredComplete: report.complete && !truncated,
|
|
26871
|
+
truncated,
|
|
26872
|
+
...report.uncertainty ? { uncertainty: report.uncertainty } : {}
|
|
26873
|
+
};
|
|
26874
|
+
}
|
|
26875
|
+
function normalizeWorkspaceRoot(value) {
|
|
26876
|
+
const trimmed = value.trim();
|
|
26877
|
+
if (!isValidPathText(trimmed)) {
|
|
26878
|
+
return null;
|
|
26879
|
+
}
|
|
26880
|
+
if (isWindowsAbsolutePath2(trimmed)) {
|
|
26881
|
+
return canonicalizeWorkspaceRoot({
|
|
26882
|
+
value: path5.win32.normalize(trimmed.replace(/\//g, "\\")),
|
|
26883
|
+
flavor: "windows"
|
|
26884
|
+
});
|
|
26885
|
+
}
|
|
26886
|
+
if (path5.posix.isAbsolute(trimmed)) {
|
|
26887
|
+
return canonicalizeWorkspaceRoot({
|
|
26888
|
+
value: path5.posix.normalize(trimmed.replace(/\\/g, "/")),
|
|
26889
|
+
flavor: "posix"
|
|
26890
|
+
});
|
|
26891
|
+
}
|
|
26892
|
+
return null;
|
|
26893
|
+
}
|
|
26894
|
+
function normalizeReportedPath(value, cwd, roots) {
|
|
26895
|
+
const trimmed = value.trim();
|
|
26896
|
+
if (!isValidPathText(trimmed) || /^[A-Za-z]:[^\\/]/.test(trimmed) || /^\\\\[?.]\\/.test(trimmed) || /^(?:\\\\|\/\/)/.test(trimmed) && !isWindowsAbsolutePath2(trimmed) || cwd.flavor === "windows" && /^\\(?!\\)/.test(trimmed) || /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(trimmed)) {
|
|
26897
|
+
return null;
|
|
26898
|
+
}
|
|
26899
|
+
let candidate;
|
|
26900
|
+
if (isWindowsAbsolutePath2(trimmed)) {
|
|
26901
|
+
candidate = { value: path5.win32.normalize(trimmed.replace(/\//g, "\\")), flavor: "windows" };
|
|
26902
|
+
} else if (path5.posix.isAbsolute(trimmed)) {
|
|
26903
|
+
candidate = { value: path5.posix.normalize(trimmed.replace(/\\/g, "/")), flavor: "posix" };
|
|
26904
|
+
} else if (cwd.flavor === "windows") {
|
|
26905
|
+
candidate = {
|
|
26906
|
+
value: path5.win32.resolve(cwd.value, trimmed.replace(/\//g, "\\")),
|
|
26907
|
+
flavor: "windows"
|
|
26908
|
+
};
|
|
26909
|
+
} else {
|
|
26910
|
+
candidate = {
|
|
26911
|
+
value: path5.posix.resolve(cwd.value, trimmed.replace(/\\/g, "/")),
|
|
26912
|
+
flavor: "posix"
|
|
26913
|
+
};
|
|
26914
|
+
}
|
|
26915
|
+
candidate = canonicalizeReportedPath(candidate);
|
|
26916
|
+
return roots.some((root) => pathIsStrictlyInside(root, candidate)) ? candidate : null;
|
|
26917
|
+
}
|
|
26918
|
+
function canonicalizeWorkspaceRoot(root) {
|
|
26919
|
+
if (!isNativePathFlavor(root.flavor)) {
|
|
26920
|
+
return root;
|
|
26921
|
+
}
|
|
26922
|
+
return { ...root, value: canonicalizeFromExistingAncestor(root.value) };
|
|
26923
|
+
}
|
|
26924
|
+
function canonicalizeReportedPath(candidate) {
|
|
26925
|
+
if (!isNativePathFlavor(candidate.flavor)) {
|
|
26926
|
+
return candidate;
|
|
26927
|
+
}
|
|
26928
|
+
const parent = canonicalizeFromExistingAncestor(path5.dirname(candidate.value));
|
|
26929
|
+
return { ...candidate, value: path5.resolve(parent, path5.basename(candidate.value)) };
|
|
26930
|
+
}
|
|
26931
|
+
function canonicalizeFromExistingAncestor(value) {
|
|
26932
|
+
const original = path5.resolve(value);
|
|
26933
|
+
let current = original;
|
|
26934
|
+
const missingSegments = [];
|
|
26935
|
+
while (true) {
|
|
26936
|
+
try {
|
|
26937
|
+
const canonical = fs7.realpathSync.native(current);
|
|
26938
|
+
return path5.resolve(canonical, ...missingSegments.reverse());
|
|
26939
|
+
} catch (error51) {
|
|
26940
|
+
if (!isMissingPathError(error51)) return original;
|
|
26941
|
+
}
|
|
26942
|
+
const parent = path5.dirname(current);
|
|
26943
|
+
if (parent === current) return original;
|
|
26944
|
+
missingSegments.push(path5.basename(current));
|
|
26945
|
+
current = parent;
|
|
26946
|
+
}
|
|
26947
|
+
}
|
|
26948
|
+
function isMissingPathError(error51) {
|
|
26949
|
+
if (typeof error51 !== "object" || error51 === null || !("code" in error51)) return false;
|
|
26950
|
+
return error51.code === "ENOENT" || error51.code === "ENOTDIR";
|
|
26951
|
+
}
|
|
26952
|
+
function isNativePathFlavor(flavor) {
|
|
26953
|
+
return process.platform === "win32" ? flavor === "windows" : flavor === "posix";
|
|
26954
|
+
}
|
|
26955
|
+
function pathIsStrictlyInside(root, candidate) {
|
|
26956
|
+
if (root.flavor !== candidate.flavor) {
|
|
26957
|
+
return false;
|
|
26958
|
+
}
|
|
26959
|
+
const pathImplementation = root.flavor === "windows" ? path5.win32 : path5.posix;
|
|
26960
|
+
const relative = pathImplementation.relative(root.value, candidate.value);
|
|
26961
|
+
return relative.length > 0 && !pathImplementation.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${pathImplementation.sep}`);
|
|
26962
|
+
}
|
|
26963
|
+
function isWindowsAbsolutePath2(value) {
|
|
26964
|
+
const portable = value.replace(/\\/g, "/");
|
|
26965
|
+
return /^[A-Za-z]:\//.test(portable) || /^\/\/[^/]+\/[^/]+(?:\/|$)/.test(portable);
|
|
26966
|
+
}
|
|
26967
|
+
function isValidPathText(value) {
|
|
26968
|
+
return value.length > 0 && !/[\u0000-\u001F\u007F-\u009F]/.test(value);
|
|
26969
|
+
}
|
|
26970
|
+
function asRecord(value) {
|
|
26971
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
26972
|
+
}
|
|
26973
|
+
function hasOnlyKeys(value, allowed) {
|
|
26974
|
+
const allowedKeys = new Set(allowed);
|
|
26975
|
+
return Object.keys(value).every((key) => allowedKeys.has(key));
|
|
26976
|
+
}
|
|
26977
|
+
|
|
26542
26978
|
// src/CodexAcpClient.ts
|
|
26543
26979
|
var CUSTOM_GATEWAY_PROVIDER_ID = "custom-gateway";
|
|
26980
|
+
var OPENAI_PROVIDER_ID = "openai";
|
|
26981
|
+
var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1";
|
|
26544
26982
|
var SUPPORTED_GATEWAY_PROTOCOLS = {
|
|
26545
26983
|
openai: "responses"
|
|
26546
26984
|
};
|
|
@@ -26754,34 +27192,47 @@ var CodexAcpClient = class {
|
|
|
26754
27192
|
};
|
|
26755
27193
|
}
|
|
26756
27194
|
/**
|
|
26757
|
-
* `providers/list`: returns
|
|
26758
|
-
*
|
|
26759
|
-
* `null` when the provider is not configured/disabled.
|
|
27195
|
+
* `providers/list`: returns Codex's OpenAI slot. With no ACP override, the
|
|
27196
|
+
* slot reports native OpenAI routing; headers are never exposed.
|
|
26760
27197
|
*/
|
|
26761
27198
|
listProviders() {
|
|
26762
27199
|
const gatewayConfig = this.gatewayConfig;
|
|
26763
27200
|
const current = gatewayConfig ? {
|
|
26764
27201
|
apiType: gatewayApiTypeFromConfig(gatewayConfig),
|
|
26765
27202
|
baseUrl: gatewayConfig.config.base_url
|
|
26766
|
-
} :
|
|
27203
|
+
} : this.getNativeProviderConfig();
|
|
26767
27204
|
return [
|
|
26768
27205
|
{
|
|
26769
|
-
providerId:
|
|
27206
|
+
providerId: OPENAI_PROVIDER_ID,
|
|
26770
27207
|
supported: Object.keys(SUPPORTED_GATEWAY_PROTOCOLS),
|
|
26771
27208
|
required: false,
|
|
26772
27209
|
current
|
|
26773
27210
|
}
|
|
26774
27211
|
];
|
|
26775
27212
|
}
|
|
27213
|
+
getNativeProviderConfig() {
|
|
27214
|
+
const configuredProviderId = this.modelProvider ?? (typeof this.config["model_provider"] === "string" ? this.config["model_provider"] : null);
|
|
27215
|
+
const configuredProviders = this.config["model_providers"];
|
|
27216
|
+
if (configuredProviderId && configuredProviders && typeof configuredProviders === "object" && !Array.isArray(configuredProviders)) {
|
|
27217
|
+
const configuredProvider = configuredProviders[configuredProviderId];
|
|
27218
|
+
if (configuredProvider && typeof configuredProvider === "object" && !Array.isArray(configuredProvider)) {
|
|
27219
|
+
const baseUrl = configuredProvider["base_url"];
|
|
27220
|
+
if (typeof baseUrl === "string" && baseUrl.length > 0) {
|
|
27221
|
+
return { apiType: "openai", baseUrl };
|
|
27222
|
+
}
|
|
27223
|
+
}
|
|
27224
|
+
}
|
|
27225
|
+
return { apiType: "openai", baseUrl: DEFAULT_OPENAI_BASE_URL };
|
|
27226
|
+
}
|
|
26776
27227
|
/**
|
|
26777
27228
|
* `providers/set`: replaces the full configuration for the custom gateway
|
|
26778
27229
|
* provider. Rejects unknown provider ids with `invalid_params`.
|
|
26779
27230
|
*/
|
|
26780
27231
|
setProvider(request) {
|
|
26781
|
-
if (request.providerId !==
|
|
27232
|
+
if (request.providerId !== OPENAI_PROVIDER_ID) {
|
|
26782
27233
|
throw RequestError.invalidParams(
|
|
26783
27234
|
{ providerId: request.providerId },
|
|
26784
|
-
`Unknown providerId "${request.providerId}"; only "${
|
|
27235
|
+
`Unknown providerId "${request.providerId}"; only "${OPENAI_PROVIDER_ID}" is configurable`
|
|
26785
27236
|
);
|
|
26786
27237
|
}
|
|
26787
27238
|
this.applyGatewayConfig({
|
|
@@ -26795,7 +27246,7 @@ var CodexAcpClient = class {
|
|
|
26795
27246
|
* unknown provider id is idempotent success (RFD behavior §7).
|
|
26796
27247
|
*/
|
|
26797
27248
|
disableProvider(request) {
|
|
26798
|
-
if (request.providerId ===
|
|
27249
|
+
if (request.providerId === OPENAI_PROVIDER_ID) {
|
|
26799
27250
|
this.gatewayConfig = null;
|
|
26800
27251
|
}
|
|
26801
27252
|
}
|
|
@@ -26993,7 +27444,7 @@ var CodexAcpClient = class {
|
|
|
26993
27444
|
if (!cwd) {
|
|
26994
27445
|
return;
|
|
26995
27446
|
}
|
|
26996
|
-
const skillExtraRoots = additionalRoots.map((root) =>
|
|
27447
|
+
const skillExtraRoots = additionalRoots.map((root) => path6.join(root, ".agents", "skills"));
|
|
26997
27448
|
if (!arraysEqual(this.skillExtraRoots, skillExtraRoots)) {
|
|
26998
27449
|
await this.codexClient.skillsExtraRootsSet({ extraRoots: skillExtraRoots });
|
|
26999
27450
|
this.skillExtraRoots = skillExtraRoots;
|
|
@@ -27115,6 +27566,113 @@ var CodexAcpClient = class {
|
|
|
27115
27566
|
serviceTier
|
|
27116
27567
|
}, onTurnStarted);
|
|
27117
27568
|
}
|
|
27569
|
+
async runAgentFileChangeReport(params) {
|
|
27570
|
+
if (params.signal?.aborted) {
|
|
27571
|
+
return createUnavailableAgentFileChangeReport(params.requestId, "cancelled");
|
|
27572
|
+
}
|
|
27573
|
+
const budget = new AgentFileChangeReportBudget(params.signal);
|
|
27574
|
+
let forkThreadId = null;
|
|
27575
|
+
let auditTurnId = null;
|
|
27576
|
+
let auditTurnCompleted = false;
|
|
27577
|
+
let lateStopReason = null;
|
|
27578
|
+
try {
|
|
27579
|
+
const forkPromise = this.codexClient.threadFork({
|
|
27580
|
+
threadId: params.sessionId,
|
|
27581
|
+
lastTurnId: params.turnId,
|
|
27582
|
+
cwd: params.workspace.cwd,
|
|
27583
|
+
approvalPolicy: "never",
|
|
27584
|
+
sandbox: "read-only",
|
|
27585
|
+
developerInstructions: AGENT_FILE_CHANGE_REPORT_DEVELOPER_INSTRUCTIONS,
|
|
27586
|
+
ephemeral: true
|
|
27587
|
+
});
|
|
27588
|
+
void forkPromise.then((fork2) => {
|
|
27589
|
+
if (lateStopReason !== null && forkThreadId === null) {
|
|
27590
|
+
void this.unsubscribeAgentFileChangeReportThread(fork2.thread.id, budget);
|
|
27591
|
+
}
|
|
27592
|
+
}, () => {
|
|
27593
|
+
});
|
|
27594
|
+
const fork = await budget.wait(forkPromise);
|
|
27595
|
+
forkThreadId = fork.thread.id;
|
|
27596
|
+
const turnPromise = this.codexClient.runTurn({
|
|
27597
|
+
threadId: forkThreadId,
|
|
27598
|
+
input: [{
|
|
27599
|
+
type: "text",
|
|
27600
|
+
text: createAgentFileChangeReportPrompt(params.workspace),
|
|
27601
|
+
text_elements: []
|
|
27602
|
+
}],
|
|
27603
|
+
cwd: params.workspace.cwd,
|
|
27604
|
+
approvalPolicy: "never",
|
|
27605
|
+
sandboxPolicy: { type: "readOnly", networkAccess: false },
|
|
27606
|
+
summary: "none",
|
|
27607
|
+
outputSchema: AGENT_FILE_CHANGE_REPORT_OUTPUT_SCHEMA
|
|
27608
|
+
}, (turnId) => {
|
|
27609
|
+
auditTurnId = turnId;
|
|
27610
|
+
if (lateStopReason !== null && forkThreadId !== null) {
|
|
27611
|
+
void this.interruptAgentFileChangeReport(forkThreadId, turnId, lateStopReason, budget);
|
|
27612
|
+
}
|
|
27613
|
+
});
|
|
27614
|
+
const outcome = await budget.wait(turnPromise);
|
|
27615
|
+
auditTurnCompleted = true;
|
|
27616
|
+
const thread = await budget.wait(this.codexClient.threadRead({
|
|
27617
|
+
threadId: forkThreadId,
|
|
27618
|
+
includeTurns: true
|
|
27619
|
+
}));
|
|
27620
|
+
const completedTurn = thread.thread.turns.find(
|
|
27621
|
+
(turn) => turn.id === outcome.turn.id
|
|
27622
|
+
);
|
|
27623
|
+
if (completedTurn === void 0) {
|
|
27624
|
+
throw new AgentFileChangeReportError(
|
|
27625
|
+
"notReported",
|
|
27626
|
+
"The completed audit turn was not present in thread history"
|
|
27627
|
+
);
|
|
27628
|
+
}
|
|
27629
|
+
return createReportedAgentFileChangeReport(
|
|
27630
|
+
params.requestId,
|
|
27631
|
+
completedTurn,
|
|
27632
|
+
params.workspace
|
|
27633
|
+
);
|
|
27634
|
+
} catch (error51) {
|
|
27635
|
+
if (error51 instanceof AgentFileChangeReportBudgetError) {
|
|
27636
|
+
lateStopReason = error51.reason;
|
|
27637
|
+
if (!auditTurnCompleted && forkThreadId !== null && auditTurnId !== null) {
|
|
27638
|
+
await this.interruptAgentFileChangeReport(
|
|
27639
|
+
forkThreadId,
|
|
27640
|
+
auditTurnId,
|
|
27641
|
+
error51.reason,
|
|
27642
|
+
budget
|
|
27643
|
+
);
|
|
27644
|
+
}
|
|
27645
|
+
return createUnavailableAgentFileChangeReport(params.requestId, error51.reason);
|
|
27646
|
+
}
|
|
27647
|
+
if (error51 instanceof AgentFileChangeReportError) {
|
|
27648
|
+
logger.log("Agent file-change report unavailable", { reason: error51.reason });
|
|
27649
|
+
return createUnavailableAgentFileChangeReport(params.requestId, error51.reason);
|
|
27650
|
+
}
|
|
27651
|
+
logger.error("Agent file-change report failed", error51);
|
|
27652
|
+
return createUnavailableAgentFileChangeReport(params.requestId, "providerError");
|
|
27653
|
+
} finally {
|
|
27654
|
+
if (forkThreadId !== null) {
|
|
27655
|
+
await this.unsubscribeAgentFileChangeReportThread(forkThreadId, budget);
|
|
27656
|
+
}
|
|
27657
|
+
}
|
|
27658
|
+
}
|
|
27659
|
+
async interruptAgentFileChangeReport(threadId, turnId, reason, budget) {
|
|
27660
|
+
this.codexClient.markTurnStale(threadId, turnId);
|
|
27661
|
+
try {
|
|
27662
|
+
await budget.wait(this.codexClient.turnInterrupt({ threadId, turnId }));
|
|
27663
|
+
} catch (error51) {
|
|
27664
|
+
logger.error(`Failed to interrupt ${reason} agent file-change report`, error51);
|
|
27665
|
+
} finally {
|
|
27666
|
+
this.codexClient.resolveTurnInterrupted(threadId, turnId);
|
|
27667
|
+
}
|
|
27668
|
+
}
|
|
27669
|
+
async unsubscribeAgentFileChangeReportThread(threadId, budget) {
|
|
27670
|
+
try {
|
|
27671
|
+
await budget.wait(this.codexClient.threadUnsubscribe({ threadId }));
|
|
27672
|
+
} catch (error51) {
|
|
27673
|
+
logger.error("Failed to unsubscribe the agent file-change report thread", error51);
|
|
27674
|
+
}
|
|
27675
|
+
}
|
|
27118
27676
|
async setCollaborationMode(sessionId, mode, currentModelId) {
|
|
27119
27677
|
await this.codexClient.threadSettingsUpdate({
|
|
27120
27678
|
threadId: sessionId,
|
|
@@ -27265,6 +27823,58 @@ var CodexAcpClient = class {
|
|
|
27265
27823
|
};
|
|
27266
27824
|
}
|
|
27267
27825
|
};
|
|
27826
|
+
var AgentFileChangeReportBudgetError = class extends Error {
|
|
27827
|
+
constructor(reason) {
|
|
27828
|
+
super(`Agent file-change report ${reason}`);
|
|
27829
|
+
this.reason = reason;
|
|
27830
|
+
this.name = "AgentFileChangeReportBudgetError";
|
|
27831
|
+
}
|
|
27832
|
+
reason;
|
|
27833
|
+
};
|
|
27834
|
+
var AgentFileChangeReportBudget = class {
|
|
27835
|
+
constructor(signal) {
|
|
27836
|
+
this.signal = signal;
|
|
27837
|
+
}
|
|
27838
|
+
signal;
|
|
27839
|
+
deadline = Date.now() + AGENT_FILE_CHANGE_REPORT_TIMEOUT_MS;
|
|
27840
|
+
async wait(operation) {
|
|
27841
|
+
void operation.catch(() => {
|
|
27842
|
+
});
|
|
27843
|
+
const immediateReason = this.stopReason();
|
|
27844
|
+
if (immediateReason !== null) {
|
|
27845
|
+
throw new AgentFileChangeReportBudgetError(immediateReason);
|
|
27846
|
+
}
|
|
27847
|
+
return await new Promise((resolve, reject) => {
|
|
27848
|
+
let settled = false;
|
|
27849
|
+
const finish = (action) => {
|
|
27850
|
+
if (settled) return;
|
|
27851
|
+
settled = true;
|
|
27852
|
+
clearTimeout(timeout);
|
|
27853
|
+
this.signal?.removeEventListener("abort", onAbort);
|
|
27854
|
+
action();
|
|
27855
|
+
};
|
|
27856
|
+
const onAbort = () => finish(() => reject(new AgentFileChangeReportBudgetError("cancelled")));
|
|
27857
|
+
const timeout = setTimeout(
|
|
27858
|
+
() => finish(() => reject(new AgentFileChangeReportBudgetError("timeout"))),
|
|
27859
|
+
Math.max(1, this.deadline - Date.now())
|
|
27860
|
+
);
|
|
27861
|
+
timeout.unref();
|
|
27862
|
+
this.signal?.addEventListener("abort", onAbort, { once: true });
|
|
27863
|
+
if (this.signal?.aborted) {
|
|
27864
|
+
onAbort();
|
|
27865
|
+
}
|
|
27866
|
+
void operation.then(
|
|
27867
|
+
(value) => finish(() => resolve(value)),
|
|
27868
|
+
(error51) => finish(() => reject(error51))
|
|
27869
|
+
);
|
|
27870
|
+
});
|
|
27871
|
+
}
|
|
27872
|
+
stopReason() {
|
|
27873
|
+
if (this.signal?.aborted) return "cancelled";
|
|
27874
|
+
if (Date.now() >= this.deadline) return "timeout";
|
|
27875
|
+
return null;
|
|
27876
|
+
}
|
|
27877
|
+
};
|
|
27268
27878
|
function buildPromptItems(prompt) {
|
|
27269
27879
|
return prompt.map((block) => {
|
|
27270
27880
|
switch (block.type) {
|
|
@@ -27324,8 +27934,8 @@ function formatUriAsLink(name, uri) {
|
|
|
27324
27934
|
return `[@${name}](${uri})`;
|
|
27325
27935
|
}
|
|
27326
27936
|
if (uri.startsWith("file://")) {
|
|
27327
|
-
const
|
|
27328
|
-
const fileName =
|
|
27937
|
+
const path8 = uri.replace("file://", "");
|
|
27938
|
+
const fileName = path8.split("/").pop() ?? path8;
|
|
27329
27939
|
return `[@${fileName}](${uri})`;
|
|
27330
27940
|
}
|
|
27331
27941
|
return uri;
|
|
@@ -27355,7 +27965,7 @@ function readAdditionalDirectories(cwd, additionalDirectories, meta3) {
|
|
|
27355
27965
|
if (directory.length === 0) {
|
|
27356
27966
|
throw RequestError.invalidParams(void 0, "additionalDirectories entries must not be empty");
|
|
27357
27967
|
}
|
|
27358
|
-
if (!
|
|
27968
|
+
if (!path6.isAbsolute(directory)) {
|
|
27359
27969
|
throw RequestError.invalidParams(void 0, "additionalDirectories entries must be absolute paths");
|
|
27360
27970
|
}
|
|
27361
27971
|
if (!seen.has(directory)) {
|
|
@@ -27958,7 +28568,7 @@ var SteeringQueue = class {
|
|
|
27958
28568
|
|
|
27959
28569
|
// src/ResponseItemHistoryFallback.ts
|
|
27960
28570
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
27961
|
-
import
|
|
28571
|
+
import path7 from "node:path";
|
|
27962
28572
|
function historyFallbackUpdateKey(update) {
|
|
27963
28573
|
switch (update.sessionUpdate) {
|
|
27964
28574
|
case "user_message_chunk":
|
|
@@ -28112,14 +28722,14 @@ function parseJsonRecord(line) {
|
|
|
28112
28722
|
}
|
|
28113
28723
|
try {
|
|
28114
28724
|
const value = JSON.parse(line);
|
|
28115
|
-
return
|
|
28725
|
+
return asRecord2(value);
|
|
28116
28726
|
} catch {
|
|
28117
28727
|
return null;
|
|
28118
28728
|
}
|
|
28119
28729
|
}
|
|
28120
28730
|
function extractResponseItem(record2) {
|
|
28121
28731
|
if (record2["type"] === "response_item") {
|
|
28122
|
-
return
|
|
28732
|
+
return asRecord2(record2["payload"]);
|
|
28123
28733
|
}
|
|
28124
28734
|
const itemType = record2["type"];
|
|
28125
28735
|
if (typeof itemType === "string" && isLegacyResponseItemType(itemType)) {
|
|
@@ -28153,7 +28763,7 @@ function createEventMsgUpdates(record2) {
|
|
|
28153
28763
|
if (record2["type"] !== "event_msg") {
|
|
28154
28764
|
return null;
|
|
28155
28765
|
}
|
|
28156
|
-
const payload =
|
|
28766
|
+
const payload = asRecord2(record2["payload"]);
|
|
28157
28767
|
if (!payload) {
|
|
28158
28768
|
return [];
|
|
28159
28769
|
}
|
|
@@ -28197,9 +28807,9 @@ function imageBlocks(images) {
|
|
|
28197
28807
|
if (typeof image === "string") {
|
|
28198
28808
|
return [{ type: "text", text: `[@image](${image})` }];
|
|
28199
28809
|
}
|
|
28200
|
-
const record2 =
|
|
28201
|
-
const
|
|
28202
|
-
return
|
|
28810
|
+
const record2 = asRecord2(image);
|
|
28811
|
+
const path8 = record2 ? stringValue(record2["path"]) ?? stringValue(record2["url"]) : null;
|
|
28812
|
+
return path8 ? [{ type: "text", text: `[@image](${path8})` }] : [];
|
|
28203
28813
|
});
|
|
28204
28814
|
}
|
|
28205
28815
|
function contentBlocksFromResponseContent(content) {
|
|
@@ -28207,7 +28817,7 @@ function contentBlocksFromResponseContent(content) {
|
|
|
28207
28817
|
return [];
|
|
28208
28818
|
}
|
|
28209
28819
|
return content.flatMap((entry) => {
|
|
28210
|
-
const record2 =
|
|
28820
|
+
const record2 = asRecord2(entry);
|
|
28211
28821
|
if (!record2) {
|
|
28212
28822
|
return [];
|
|
28213
28823
|
}
|
|
@@ -28240,7 +28850,7 @@ function textParts(value) {
|
|
|
28240
28850
|
if (typeof entry === "string") {
|
|
28241
28851
|
return entry.length > 0 ? [entry] : [];
|
|
28242
28852
|
}
|
|
28243
|
-
const record2 =
|
|
28853
|
+
const record2 = asRecord2(entry);
|
|
28244
28854
|
if (!record2) {
|
|
28245
28855
|
return [];
|
|
28246
28856
|
}
|
|
@@ -28332,7 +28942,7 @@ function parseFunctionArguments(value) {
|
|
|
28332
28942
|
}
|
|
28333
28943
|
function rawInputForFunctionCall(name, args) {
|
|
28334
28944
|
if (name === "exec_command") {
|
|
28335
|
-
const record2 =
|
|
28945
|
+
const record2 = asRecord2(args);
|
|
28336
28946
|
if (record2) {
|
|
28337
28947
|
return {
|
|
28338
28948
|
command: stringValue(record2["cmd"]) ?? stringValue(record2["command"]),
|
|
@@ -28379,14 +28989,14 @@ function functionCallUsesTerminal(item) {
|
|
|
28379
28989
|
return item["name"] === "exec_command";
|
|
28380
28990
|
}
|
|
28381
28991
|
function commandFromFunctionArguments(args) {
|
|
28382
|
-
const record2 =
|
|
28992
|
+
const record2 = asRecord2(args);
|
|
28383
28993
|
if (!record2) {
|
|
28384
28994
|
return null;
|
|
28385
28995
|
}
|
|
28386
28996
|
return stringValue(record2["cmd"]) ?? stringValue(record2["command"]);
|
|
28387
28997
|
}
|
|
28388
28998
|
function cwdFromFunctionArguments(args) {
|
|
28389
|
-
const record2 =
|
|
28999
|
+
const record2 = asRecord2(args);
|
|
28390
29000
|
if (!record2) {
|
|
28391
29001
|
return "";
|
|
28392
29002
|
}
|
|
@@ -28831,10 +29441,10 @@ function baseCommandName(commandName) {
|
|
|
28831
29441
|
return commandName.split(/[\\/]/).pop() ?? commandName;
|
|
28832
29442
|
}
|
|
28833
29443
|
function absolutizePath(cwd, targetPath) {
|
|
28834
|
-
if (
|
|
29444
|
+
if (path7.isAbsolute(targetPath) || cwd.length === 0) {
|
|
28835
29445
|
return targetPath;
|
|
28836
29446
|
}
|
|
28837
|
-
return
|
|
29447
|
+
return path7.join(cwd, targetPath);
|
|
28838
29448
|
}
|
|
28839
29449
|
function withTerminalContent(event, terminalId, cwd) {
|
|
28840
29450
|
const { rawInput, ...eventWithoutRawInput } = event;
|
|
@@ -28858,7 +29468,7 @@ function outputText(output) {
|
|
|
28858
29468
|
return "";
|
|
28859
29469
|
}
|
|
28860
29470
|
return output.flatMap((entry) => {
|
|
28861
|
-
const record2 =
|
|
29471
|
+
const record2 = asRecord2(entry);
|
|
28862
29472
|
if (!record2) {
|
|
28863
29473
|
return [];
|
|
28864
29474
|
}
|
|
@@ -28874,7 +29484,7 @@ function outputText(output) {
|
|
|
28874
29484
|
}).join("\n");
|
|
28875
29485
|
}
|
|
28876
29486
|
function parseExitCode(rawOutput, output) {
|
|
28877
|
-
const record2 =
|
|
29487
|
+
const record2 = asRecord2(rawOutput);
|
|
28878
29488
|
if (record2) {
|
|
28879
29489
|
const exitCode2 = numberValue(record2["exit_code"]) ?? numberValue(record2["exitCode"]);
|
|
28880
29490
|
if (exitCode2 !== null) {
|
|
@@ -28905,7 +29515,7 @@ function looksLikeCommandFailure(output) {
|
|
|
28905
29515
|
}
|
|
28906
29516
|
return /(^|\n)(Error|Failed|Command failed|Sandbox error|No such file or directory|Permission denied|Operation not permitted|ENOENT|EACCES)(:|\b)/i.test(trimmed);
|
|
28907
29517
|
}
|
|
28908
|
-
function
|
|
29518
|
+
function asRecord2(value) {
|
|
28909
29519
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
28910
29520
|
return null;
|
|
28911
29521
|
}
|
|
@@ -28994,12 +29604,18 @@ import { randomUUID as randomUUID2 } from "node:crypto";
|
|
|
28994
29604
|
var IMPLEMENT_PLAN_OPTION_ID = "implement_plan";
|
|
28995
29605
|
var REVISE_PLAN_OPTION_ID = "revise_plan";
|
|
28996
29606
|
var CODEX_PROCESS_EXITED_ERROR_CODE = 1001;
|
|
28997
|
-
function
|
|
29607
|
+
function clientSupportsAirCapability(capabilities, capability) {
|
|
28998
29608
|
const jetbrains = capabilities?._meta?.[JETBRAINS_META_KEY];
|
|
28999
29609
|
const air = jetbrains?.[AIR_META_KEY];
|
|
29000
29610
|
const version2 = air?.[AIR_EXTENSION_VERSION_KEY];
|
|
29001
29611
|
const supported = air?.[AIR_EXTENSION_CAPABILITIES_KEY];
|
|
29002
|
-
return typeof version2 === "number" && Number.isInteger(version2) && version2 >= AIR_EXTENSION_VERSION && Array.isArray(supported) && supported.includes(
|
|
29612
|
+
return typeof version2 === "number" && Number.isInteger(version2) && version2 >= AIR_EXTENSION_VERSION && Array.isArray(supported) && supported.includes(capability);
|
|
29613
|
+
}
|
|
29614
|
+
function clientSupportsTypedSessionFailures(capabilities) {
|
|
29615
|
+
return clientSupportsAirCapability(capabilities, AIR_SESSION_FAILURE_KEY);
|
|
29616
|
+
}
|
|
29617
|
+
function clientSupportsAgentFileChangeReports(capabilities) {
|
|
29618
|
+
return clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY);
|
|
29003
29619
|
}
|
|
29004
29620
|
var CodexAcpServer = class _CodexAcpServer {
|
|
29005
29621
|
static MODEL_NAME_TOKEN_OVERRIDES = {
|
|
@@ -29104,7 +29720,10 @@ var CodexAcpServer = class _CodexAcpServer {
|
|
|
29104
29720
|
[JETBRAINS_META_KEY]: {
|
|
29105
29721
|
[AIR_META_KEY]: {
|
|
29106
29722
|
[AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
|
|
29107
|
-
[AIR_EXTENSION_CAPABILITIES_KEY]: [
|
|
29723
|
+
[AIR_EXTENSION_CAPABILITIES_KEY]: [
|
|
29724
|
+
AIR_SESSION_FAILURE_KEY,
|
|
29725
|
+
AIR_AGENT_FILE_CHANGE_REPORT_KEY
|
|
29726
|
+
]
|
|
29108
29727
|
}
|
|
29109
29728
|
}
|
|
29110
29729
|
}
|
|
@@ -30155,6 +30774,42 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30155
30774
|
title
|
|
30156
30775
|
});
|
|
30157
30776
|
}
|
|
30777
|
+
async publishAgentFileChangeReport(sessionState, turnId, request, unavailableReason, signal) {
|
|
30778
|
+
let report;
|
|
30779
|
+
try {
|
|
30780
|
+
report = turnId === null ? createUnavailableAgentFileChangeReport(request.requestId, unavailableReason) : await this.codexAcpClient.runAgentFileChangeReport({
|
|
30781
|
+
sessionId: sessionState.sessionId,
|
|
30782
|
+
turnId,
|
|
30783
|
+
// The client owns request-id correlation and duplicate suppression. The wrapper
|
|
30784
|
+
// stays stateless so a retried ACP prompt still receives a terminal report.
|
|
30785
|
+
requestId: request.requestId,
|
|
30786
|
+
workspace: {
|
|
30787
|
+
cwd: sessionState.cwd,
|
|
30788
|
+
additionalDirectories: sessionState.additionalDirectories
|
|
30789
|
+
},
|
|
30790
|
+
signal
|
|
30791
|
+
});
|
|
30792
|
+
} catch (error51) {
|
|
30793
|
+
logger.error("Agent file-change report failed unexpectedly", error51);
|
|
30794
|
+
report = createUnavailableAgentFileChangeReport(request.requestId, "providerError");
|
|
30795
|
+
}
|
|
30796
|
+
try {
|
|
30797
|
+
const session = new ACPSessionConnection(this.connection, sessionState.sessionId);
|
|
30798
|
+
await session.update({
|
|
30799
|
+
sessionUpdate: "session_info_update",
|
|
30800
|
+
_meta: {
|
|
30801
|
+
[JETBRAINS_META_KEY]: {
|
|
30802
|
+
[AIR_META_KEY]: {
|
|
30803
|
+
[AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
|
|
30804
|
+
[AIR_AGENT_FILE_CHANGE_REPORT_KEY]: report
|
|
30805
|
+
}
|
|
30806
|
+
}
|
|
30807
|
+
}
|
|
30808
|
+
});
|
|
30809
|
+
} catch (error51) {
|
|
30810
|
+
logger.error("Failed to publish agent file-change report", error51);
|
|
30811
|
+
}
|
|
30812
|
+
}
|
|
30158
30813
|
createPromptFallbackTitle(prompt) {
|
|
30159
30814
|
return this.normalizeSessionTitle(prompt.filter((block) => block.type === "text").map((block) => block.text).join(" "));
|
|
30160
30815
|
}
|
|
@@ -30289,8 +30944,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30289
30944
|
return `[@${name}](${uri})`;
|
|
30290
30945
|
}
|
|
30291
30946
|
if (uri.startsWith("file://")) {
|
|
30292
|
-
const
|
|
30293
|
-
const fileName =
|
|
30947
|
+
const path8 = uri.replace("file://", "");
|
|
30948
|
+
const fileName = path8.split("/").pop() ?? path8;
|
|
30294
30949
|
return `[@${fileName}](${uri})`;
|
|
30295
30950
|
}
|
|
30296
30951
|
return uri;
|
|
@@ -30543,6 +31198,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30543
31198
|
prompt: params.prompt
|
|
30544
31199
|
});
|
|
30545
31200
|
const sessionState = this.getSessionState(params.sessionId);
|
|
31201
|
+
const agentFileChangeReportRequest = clientSupportsAgentFileChangeReports(this.clientCapabilities) ? parseAgentFileChangeReportRequest(params._meta) : null;
|
|
31202
|
+
let agentFileChangeReportTurnId = null;
|
|
31203
|
+
let agentFileChangeReportUnavailableReason = "providerError";
|
|
30546
31204
|
let recoverableSessionFailure = sessionState.sessionFailure;
|
|
30547
31205
|
sessionState.currentTurnId = null;
|
|
30548
31206
|
sessionState.lastTokenUsage = null;
|
|
@@ -30559,11 +31217,17 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30559
31217
|
let eventHandler = null;
|
|
30560
31218
|
let promptNotificationsActive = true;
|
|
30561
31219
|
const clearRecoveredSessionFailure = async (handler) => {
|
|
31220
|
+
await handler.completeSuccessfulTurn(sessionState.currentTurnId);
|
|
30562
31221
|
const current = sessionState.sessionFailure;
|
|
30563
|
-
if (recoverableSessionFailure
|
|
31222
|
+
if (recoverableSessionFailure !== void 0 && current !== void 0 && current.id === recoverableSessionFailure.id && current.revision === recoverableSessionFailure.revision) {
|
|
30564
31223
|
await handler.clearSessionFailure();
|
|
30565
31224
|
}
|
|
30566
31225
|
};
|
|
31226
|
+
const cancelledPromptResponse = () => {
|
|
31227
|
+
agentFileChangeReportTurnId = null;
|
|
31228
|
+
agentFileChangeReportUnavailableReason = "cancelled";
|
|
31229
|
+
return this.cancelledPromptResponse(sessionState);
|
|
31230
|
+
};
|
|
30567
31231
|
try {
|
|
30568
31232
|
const promptEventHandler = new CodexEventHandler(
|
|
30569
31233
|
this.connection,
|
|
@@ -30598,7 +31262,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30598
31262
|
elicitationHandler
|
|
30599
31263
|
);
|
|
30600
31264
|
if (activePrompt.signal.aborted) {
|
|
30601
|
-
return
|
|
31265
|
+
return cancelledPromptResponse();
|
|
30602
31266
|
}
|
|
30603
31267
|
const commandPromise = this.availableCommands.tryHandleCommand(params.prompt, sessionState, {
|
|
30604
31268
|
onTurnStartPending: () => {
|
|
@@ -30639,7 +31303,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30639
31303
|
this.cancelBeforeTurnStarted(activePrompt)
|
|
30640
31304
|
]);
|
|
30641
31305
|
if (commandResult === null) {
|
|
30642
|
-
return
|
|
31306
|
+
return cancelledPromptResponse();
|
|
30643
31307
|
}
|
|
30644
31308
|
if (commandResult.handled) {
|
|
30645
31309
|
promptNotificationsActive = false;
|
|
@@ -30651,7 +31315,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30651
31315
|
await eventHandler.handleFailedTurn(commandResult.turnCompleted.turn);
|
|
30652
31316
|
}
|
|
30653
31317
|
if (commandResult.turnCompleted?.turn.status === "interrupted") {
|
|
30654
|
-
return
|
|
31318
|
+
return cancelledPromptResponse();
|
|
30655
31319
|
}
|
|
30656
31320
|
const error52 = eventHandler.getFailure();
|
|
30657
31321
|
if (error52) {
|
|
@@ -30665,6 +31329,11 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30665
31329
|
if (terminalFailure2) {
|
|
30666
31330
|
return terminalFailure2;
|
|
30667
31331
|
}
|
|
31332
|
+
if (commandResult.turnCompleted?.turn.status === "completed") {
|
|
31333
|
+
agentFileChangeReportTurnId = commandResult.turnCompleted.turn.id;
|
|
31334
|
+
} else if (commandResult.turnCompleted === void 0) {
|
|
31335
|
+
agentFileChangeReportUnavailableReason = "notReported";
|
|
31336
|
+
}
|
|
30668
31337
|
await clearRecoveredSessionFailure(eventHandler);
|
|
30669
31338
|
return {
|
|
30670
31339
|
stopReason: "end_turn",
|
|
@@ -30674,7 +31343,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30674
31343
|
}
|
|
30675
31344
|
const effectiveParams = commandResult.prompt === void 0 ? params : { ...params, prompt: commandResult.prompt };
|
|
30676
31345
|
if (this.sessionIsClosing(params.sessionId)) {
|
|
30677
|
-
return
|
|
31346
|
+
return cancelledPromptResponse();
|
|
30678
31347
|
}
|
|
30679
31348
|
const modelId = ModelId.fromString(sessionState.currentModelId);
|
|
30680
31349
|
const modelLacksReasoning = sessionState.supportedReasoningEfforts.length > 0 && sessionState.supportedReasoningEfforts.every((e) => e.reasoningEffort === "none");
|
|
@@ -30728,7 +31397,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30728
31397
|
this.cancelBeforeTurnStarted(activePrompt)
|
|
30729
31398
|
]);
|
|
30730
31399
|
if (turnCompleted === null) {
|
|
30731
|
-
return
|
|
31400
|
+
return cancelledPromptResponse();
|
|
30732
31401
|
}
|
|
30733
31402
|
await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
|
|
30734
31403
|
await eventHandler.flushPendingErrors();
|
|
@@ -30736,7 +31405,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30736
31405
|
promptNotificationsActive = false;
|
|
30737
31406
|
if (turnCompleted.turn.status === "interrupted") {
|
|
30738
31407
|
await eventHandler.flushPendingPlanUpdates();
|
|
30739
|
-
return
|
|
31408
|
+
return cancelledPromptResponse();
|
|
30740
31409
|
}
|
|
30741
31410
|
const error51 = eventHandler.getFailure();
|
|
30742
31411
|
if (error51) {
|
|
@@ -30759,7 +31428,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30759
31428
|
activePrompt.signal
|
|
30760
31429
|
);
|
|
30761
31430
|
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
30762
|
-
return
|
|
31431
|
+
return cancelledPromptResponse();
|
|
30763
31432
|
}
|
|
30764
31433
|
if (approved && !this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
30765
31434
|
await this.applyCollaborationModeChange(sessionState, DEFAULT_COLLABORATION_MODE);
|
|
@@ -30808,7 +31477,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30808
31477
|
this.cancelBeforeTurnStarted(activePrompt)
|
|
30809
31478
|
]);
|
|
30810
31479
|
if (turnCompleted === null) {
|
|
30811
|
-
return
|
|
31480
|
+
return cancelledPromptResponse();
|
|
30812
31481
|
}
|
|
30813
31482
|
await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
|
|
30814
31483
|
await eventHandler.flushPendingErrors();
|
|
@@ -30816,7 +31485,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30816
31485
|
promptNotificationsActive = false;
|
|
30817
31486
|
if (turnCompleted.turn.status === "interrupted") {
|
|
30818
31487
|
await eventHandler.flushPendingPlanUpdates();
|
|
30819
|
-
return
|
|
31488
|
+
return cancelledPromptResponse();
|
|
30820
31489
|
}
|
|
30821
31490
|
const implementationError = eventHandler.getFailure();
|
|
30822
31491
|
if (implementationError) {
|
|
@@ -30832,6 +31501,9 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30832
31501
|
}
|
|
30833
31502
|
}
|
|
30834
31503
|
}
|
|
31504
|
+
if (turnCompleted.turn.status === "completed") {
|
|
31505
|
+
agentFileChangeReportTurnId = turnCompleted.turn.id;
|
|
31506
|
+
}
|
|
30835
31507
|
await clearRecoveredSessionFailure(eventHandler);
|
|
30836
31508
|
await this.publishFallbackSessionTitle(
|
|
30837
31509
|
sessionState,
|
|
@@ -30845,13 +31517,17 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30845
31517
|
} catch (err) {
|
|
30846
31518
|
logger.error(`Prompt for session ${params.sessionId} failed`, err);
|
|
30847
31519
|
if (activePrompt.signal.aborted || this.sessionIsClosing(params.sessionId)) {
|
|
30848
|
-
return
|
|
31520
|
+
return cancelledPromptResponse();
|
|
30849
31521
|
}
|
|
31522
|
+
agentFileChangeReportTurnId = null;
|
|
31523
|
+
agentFileChangeReportUnavailableReason = "providerError";
|
|
30850
31524
|
const isProcessExit = err instanceof RequestError && err.code === CODEX_PROCESS_EXITED_ERROR_CODE;
|
|
30851
31525
|
const isUnexpectedFailure = !(err instanceof RequestError);
|
|
30852
31526
|
if (eventHandler !== null && clientSupportsTypedSessionFailures(this.clientCapabilities) && (isProcessExit || isUnexpectedFailure)) {
|
|
30853
|
-
|
|
30854
|
-
|
|
31527
|
+
eventHandler.recordSyntheticTerminalFailure(
|
|
31528
|
+
isProcessExit ? "transport_lost" : "internal_error",
|
|
31529
|
+
sessionState.currentTurnId
|
|
31530
|
+
);
|
|
30855
31531
|
const failureResponse = this.terminalFailurePromptResponse(
|
|
30856
31532
|
sessionState,
|
|
30857
31533
|
eventHandler,
|
|
@@ -30865,6 +31541,15 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
30865
31541
|
throw err;
|
|
30866
31542
|
} finally {
|
|
30867
31543
|
promptNotificationsActive = false;
|
|
31544
|
+
if (agentFileChangeReportRequest !== null) {
|
|
31545
|
+
await this.publishAgentFileChangeReport(
|
|
31546
|
+
sessionState,
|
|
31547
|
+
agentFileChangeReportTurnId,
|
|
31548
|
+
agentFileChangeReportRequest,
|
|
31549
|
+
agentFileChangeReportUnavailableReason,
|
|
31550
|
+
activePrompt.signal
|
|
31551
|
+
);
|
|
31552
|
+
}
|
|
30868
31553
|
logger.log("Prompt completed", { sessionId: params.sessionId });
|
|
30869
31554
|
await eventHandler?.dispose();
|
|
30870
31555
|
disposePromptRequestCancellation();
|
|
@@ -31427,6 +32112,9 @@ var CodexAppServerClient = class {
|
|
|
31427
32112
|
async threadResume(params) {
|
|
31428
32113
|
return await this.sendRequest({ method: "thread/resume", params });
|
|
31429
32114
|
}
|
|
32115
|
+
async threadFork(params) {
|
|
32116
|
+
return await this.sendRequest({ method: "thread/fork", params });
|
|
32117
|
+
}
|
|
31430
32118
|
getThreadSettings(threadId) {
|
|
31431
32119
|
return this.threadSettings.get(threadId);
|
|
31432
32120
|
}
|