lody 0.97.2 → 0.98.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/chunks/{index-5o35kMTc.js → index-DGod--yP.js} +880 -709
- package/dist/chunks/{package-CZY_YQI4.js → package-BdifTDFO.js} +1 -1
- package/dist/chunks/{acp-DCoAUZc7.js → profile-BmD8b-zH.js} +434 -36
- package/dist/chunks/{review-viewer-Dah28phN.js → review-viewer-wpzL1tfQ.js} +4 -5
- package/dist/chunks/{runtime-manifest-DqfOlvSw.js → runtime-manifest-DZsDOOW3.js} +1 -1
- package/dist/claude-acp.js +12689 -7932
- package/dist/codex-acp.js +1 -1
- package/dist/deepseek-acp.js +352 -166
- package/dist/grok-acp.js +236 -32
- package/dist/index.js +540 -243
- package/package.json +1 -1
- package/dist/chunks/profile-DQaC7SJZ.js +0 -430
|
@@ -128,30 +128,30 @@ var require_messages = __commonJS({
|
|
|
128
128
|
Object.defineProperty(exports$1, "__esModule", { value: true });
|
|
129
129
|
exports$1.Message = exports$1.NotificationType9 = exports$1.NotificationType8 = exports$1.NotificationType7 = exports$1.NotificationType6 = exports$1.NotificationType5 = exports$1.NotificationType4 = exports$1.NotificationType3 = exports$1.NotificationType2 = exports$1.NotificationType1 = exports$1.NotificationType0 = exports$1.NotificationType = exports$1.RequestType9 = exports$1.RequestType8 = exports$1.RequestType7 = exports$1.RequestType6 = exports$1.RequestType5 = exports$1.RequestType4 = exports$1.RequestType3 = exports$1.RequestType2 = exports$1.RequestType1 = exports$1.RequestType = exports$1.RequestType0 = exports$1.AbstractMessageSignature = exports$1.ParameterStructures = exports$1.ResponseError = exports$1.ErrorCodes = void 0;
|
|
130
130
|
var is = __importStar(require_is());
|
|
131
|
-
var
|
|
132
|
-
(function(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
})(
|
|
149
|
-
var
|
|
131
|
+
var ErrorCodes2;
|
|
132
|
+
(function(ErrorCodes3) {
|
|
133
|
+
ErrorCodes3.ParseError = -32700;
|
|
134
|
+
ErrorCodes3.InvalidRequest = -32600;
|
|
135
|
+
ErrorCodes3.MethodNotFound = -32601;
|
|
136
|
+
ErrorCodes3.InvalidParams = -32602;
|
|
137
|
+
ErrorCodes3.InternalError = -32603;
|
|
138
|
+
ErrorCodes3.jsonrpcReservedErrorRangeStart = -32099;
|
|
139
|
+
ErrorCodes3.serverErrorStart = -32099;
|
|
140
|
+
ErrorCodes3.MessageWriteError = -32099;
|
|
141
|
+
ErrorCodes3.MessageReadError = -32098;
|
|
142
|
+
ErrorCodes3.PendingResponseRejected = -32097;
|
|
143
|
+
ErrorCodes3.ConnectionInactive = -32096;
|
|
144
|
+
ErrorCodes3.ServerNotInitialized = -32002;
|
|
145
|
+
ErrorCodes3.UnknownErrorCode = -32001;
|
|
146
|
+
ErrorCodes3.jsonrpcReservedErrorRangeEnd = -32e3;
|
|
147
|
+
ErrorCodes3.serverErrorEnd = -32e3;
|
|
148
|
+
})(ErrorCodes2 || (exports$1.ErrorCodes = ErrorCodes2 = {}));
|
|
149
|
+
var ResponseError2 = class _ResponseError extends Error {
|
|
150
150
|
code;
|
|
151
151
|
data;
|
|
152
152
|
constructor(code, message, data) {
|
|
153
153
|
super(message);
|
|
154
|
-
this.code = is.number(code) ? code :
|
|
154
|
+
this.code = is.number(code) ? code : ErrorCodes2.UnknownErrorCode;
|
|
155
155
|
this.data = data;
|
|
156
156
|
Object.setPrototypeOf(this, _ResponseError.prototype);
|
|
157
157
|
}
|
|
@@ -166,7 +166,7 @@ var require_messages = __commonJS({
|
|
|
166
166
|
return result;
|
|
167
167
|
}
|
|
168
168
|
};
|
|
169
|
-
exports$1.ResponseError =
|
|
169
|
+
exports$1.ResponseError = ResponseError2;
|
|
170
170
|
var ParameterStructures = class _ParameterStructures {
|
|
171
171
|
kind;
|
|
172
172
|
/**
|
|
@@ -21903,6 +21903,107 @@ function reversePatch(structuredPatch) {
|
|
|
21903
21903
|
}
|
|
21904
21904
|
return reversed;
|
|
21905
21905
|
}
|
|
21906
|
+
var DiffStatsCalculator = class {
|
|
21907
|
+
addedFile(text) {
|
|
21908
|
+
return { version: 1, added: this.lineCount(text), removed: 0 };
|
|
21909
|
+
}
|
|
21910
|
+
deletedFile(text) {
|
|
21911
|
+
return { version: 1, added: 0, removed: this.lineCount(text) };
|
|
21912
|
+
}
|
|
21913
|
+
update(patch) {
|
|
21914
|
+
if (patch.isBinary || patch.hunks.length === 0) return null;
|
|
21915
|
+
let added = 0;
|
|
21916
|
+
let removed = 0;
|
|
21917
|
+
let previousOldEnd = 1;
|
|
21918
|
+
let previousNewEnd = 1;
|
|
21919
|
+
for (const hunk of patch.hunks) {
|
|
21920
|
+
const { oldStart, oldLines, newStart, newLines } = hunk;
|
|
21921
|
+
if (![oldStart, oldLines, newStart, newLines].every(Number.isSafeInteger) || oldStart < previousOldEnd || newStart < previousNewEnd || oldLines < 0 || newLines < 0 || newStart - oldStart !== added - removed) return null;
|
|
21922
|
+
let oldConsumed = 0;
|
|
21923
|
+
let newConsumed = 0;
|
|
21924
|
+
let previousWasContent = false;
|
|
21925
|
+
for (const line of hunk.lines) {
|
|
21926
|
+
switch (line[0]) {
|
|
21927
|
+
case "+":
|
|
21928
|
+
added++;
|
|
21929
|
+
newConsumed++;
|
|
21930
|
+
previousWasContent = true;
|
|
21931
|
+
break;
|
|
21932
|
+
case "-":
|
|
21933
|
+
removed++;
|
|
21934
|
+
oldConsumed++;
|
|
21935
|
+
previousWasContent = true;
|
|
21936
|
+
break;
|
|
21937
|
+
case " ":
|
|
21938
|
+
case void 0:
|
|
21939
|
+
oldConsumed++;
|
|
21940
|
+
newConsumed++;
|
|
21941
|
+
previousWasContent = true;
|
|
21942
|
+
break;
|
|
21943
|
+
case "\\":
|
|
21944
|
+
if (!previousWasContent || line.replace(/\r$/, "") !== "\") return null;
|
|
21945
|
+
previousWasContent = false;
|
|
21946
|
+
break;
|
|
21947
|
+
default:
|
|
21948
|
+
return null;
|
|
21949
|
+
}
|
|
21950
|
+
}
|
|
21951
|
+
if (oldConsumed !== oldLines || newConsumed !== newLines) return null;
|
|
21952
|
+
previousOldEnd = oldStart + oldLines;
|
|
21953
|
+
previousNewEnd = newStart + newLines;
|
|
21954
|
+
}
|
|
21955
|
+
return { version: 1, added, removed };
|
|
21956
|
+
}
|
|
21957
|
+
lineCount(text) {
|
|
21958
|
+
let count = 0;
|
|
21959
|
+
for (let offset = text.indexOf("\n"); offset >= 0; offset = text.indexOf("\n", offset + 1)) count++;
|
|
21960
|
+
for (let offset = text.indexOf("\r"); offset >= 0; offset = text.indexOf("\r", offset + 1)) {
|
|
21961
|
+
if (text[offset + 1] !== "\n") count++;
|
|
21962
|
+
}
|
|
21963
|
+
if (text.length > 0 && !text.endsWith("\n") && !text.endsWith("\r")) count++;
|
|
21964
|
+
return count;
|
|
21965
|
+
}
|
|
21966
|
+
};
|
|
21967
|
+
var JETBRAINS_META_KEY = "jetbrains";
|
|
21968
|
+
var AIR_META_KEY = "air";
|
|
21969
|
+
var AIR_EXTENSION_VERSION_KEY = "version";
|
|
21970
|
+
var AIR_EXTENSION_CAPABILITIES_KEY = "capabilities";
|
|
21971
|
+
var AIR_DIFF_STATS_KEY = "diffStats";
|
|
21972
|
+
var AIR_SESSION_FAILURE_KEY = "sessionFailure";
|
|
21973
|
+
var AIR_AGENT_FILE_CHANGE_REPORT_KEY = "agentFileChangeReport";
|
|
21974
|
+
var AIR_NATIVE_SUBAGENT_SESSIONS_KEY = "nativeSubagentSessions";
|
|
21975
|
+
var AIR_ASYNC_TASKS_KEY = "asyncTasks";
|
|
21976
|
+
var AIR_RECOMMENDED_CONFIG_VALUE_KEY = "recommendedValue";
|
|
21977
|
+
var AIR_ASYNC_TASKS_BACKGROUNDED_KEY = "backgrounded";
|
|
21978
|
+
var AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY = "agentFileChangeReportRequest";
|
|
21979
|
+
var AIR_EXTENSION_VERSION = 1;
|
|
21980
|
+
function withAirMeta(meta3, key, value) {
|
|
21981
|
+
const root = asRecord(meta3);
|
|
21982
|
+
const jetbrains = asRecord(root[JETBRAINS_META_KEY]);
|
|
21983
|
+
const air = asRecord(jetbrains[AIR_META_KEY]);
|
|
21984
|
+
return {
|
|
21985
|
+
...root,
|
|
21986
|
+
[JETBRAINS_META_KEY]: {
|
|
21987
|
+
...jetbrains,
|
|
21988
|
+
[AIR_META_KEY]: {
|
|
21989
|
+
...air,
|
|
21990
|
+
[AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
|
|
21991
|
+
[key]: value
|
|
21992
|
+
}
|
|
21993
|
+
}
|
|
21994
|
+
};
|
|
21995
|
+
}
|
|
21996
|
+
function clientSupportsAirCapability(capabilities, capability) {
|
|
21997
|
+
const meta3 = asRecord(capabilities?._meta);
|
|
21998
|
+
const jetbrains = asRecord(meta3[JETBRAINS_META_KEY]);
|
|
21999
|
+
const air = asRecord(jetbrains[AIR_META_KEY]);
|
|
22000
|
+
const version2 = air[AIR_EXTENSION_VERSION_KEY];
|
|
22001
|
+
const supported = air[AIR_EXTENSION_CAPABILITIES_KEY];
|
|
22002
|
+
return typeof version2 === "number" && Number.isInteger(version2) && version2 >= AIR_EXTENSION_VERSION && Array.isArray(supported) && supported.includes(capability);
|
|
22003
|
+
}
|
|
22004
|
+
function asRecord(value) {
|
|
22005
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
22006
|
+
}
|
|
21906
22007
|
function stripShellPrefix(command) {
|
|
21907
22008
|
const withoutShell = command.replace(/^(?:\/bin\/)?(?:bash|zsh|sh)\s+(?:-[lc]+\s+)?/, "");
|
|
21908
22009
|
if (withoutShell.startsWith("'") && withoutShell.endsWith("'")) {
|
|
@@ -21950,8 +22051,24 @@ function createContextCompactionMeta(metadata = {}) {
|
|
|
21950
22051
|
}
|
|
21951
22052
|
};
|
|
21952
22053
|
}
|
|
22054
|
+
function functionToolName(name, namespace) {
|
|
22055
|
+
return `${namespace ?? ""}${name}`;
|
|
22056
|
+
}
|
|
22057
|
+
function commandToolName(source) {
|
|
22058
|
+
switch (source) {
|
|
22059
|
+
case "unifiedExecStartup":
|
|
22060
|
+
return "exec_command";
|
|
22061
|
+
case "unifiedExecInteraction":
|
|
22062
|
+
return "write_stdin";
|
|
22063
|
+
// These sources do not identify a unique model tool.
|
|
22064
|
+
case "agent":
|
|
22065
|
+
case "userShell":
|
|
22066
|
+
return void 0;
|
|
22067
|
+
}
|
|
22068
|
+
}
|
|
21953
22069
|
var imageGenerationMeta = { lody: { toolName: LODY_TOOL_NAMES.imageGeneration } };
|
|
21954
22070
|
var CONTEXT_COMPACTION_META = createContextCompactionMeta();
|
|
22071
|
+
var DIFF_STATS = new DiffStatsCalculator();
|
|
21955
22072
|
function toAcpStatus(status) {
|
|
21956
22073
|
switch (status) {
|
|
21957
22074
|
case "inProgress":
|
|
@@ -21980,14 +22097,19 @@ async function createFileChangeUpdate(item) {
|
|
|
21980
22097
|
};
|
|
21981
22098
|
}
|
|
21982
22099
|
async function createCommandExecutionUpdate(item) {
|
|
22100
|
+
const name = commandToolName(item.source);
|
|
21983
22101
|
const commandAction = item.commandActions.length === 1 ? item.commandActions[0] : void 0;
|
|
21984
22102
|
if (commandAction) {
|
|
21985
|
-
return
|
|
22103
|
+
return {
|
|
22104
|
+
...createCommandActionEvent(item.id, item.status, item.cwd, commandAction),
|
|
22105
|
+
...name === void 0 ? {} : { name }
|
|
22106
|
+
};
|
|
21986
22107
|
}
|
|
21987
22108
|
const command = stripShellPrefix(item.command);
|
|
21988
22109
|
return createTerminalCommandEvent({
|
|
21989
22110
|
sessionUpdate: "tool_call",
|
|
21990
22111
|
toolCallId: item.id,
|
|
22112
|
+
...name === void 0 ? {} : { name },
|
|
21991
22113
|
kind: "execute",
|
|
21992
22114
|
title: command,
|
|
21993
22115
|
status: toAcpStatus(item.status),
|
|
@@ -22042,7 +22164,10 @@ async function createMcpToolCallUpdate(item) {
|
|
|
22042
22164
|
};
|
|
22043
22165
|
}
|
|
22044
22166
|
async function createDynamicToolCallUpdate(item) {
|
|
22045
|
-
return
|
|
22167
|
+
return {
|
|
22168
|
+
...await createExecuteToolCallUpdate(item, item.tool, { arguments: item.arguments }),
|
|
22169
|
+
name: functionToolName(item.tool, item.namespace)
|
|
22170
|
+
};
|
|
22046
22171
|
}
|
|
22047
22172
|
function createImageViewUpdate(item) {
|
|
22048
22173
|
const displayPath = item.path;
|
|
@@ -22050,6 +22175,7 @@ function createImageViewUpdate(item) {
|
|
|
22050
22175
|
sessionUpdate: "tool_call",
|
|
22051
22176
|
toolCallId: item.id,
|
|
22052
22177
|
kind: "read",
|
|
22178
|
+
name: "view_image",
|
|
22053
22179
|
title: `View Image ${displayPath}`,
|
|
22054
22180
|
status: "completed",
|
|
22055
22181
|
content: [createContent({
|
|
@@ -22633,53 +22759,43 @@ async function createAddFileContent(change) {
|
|
|
22633
22759
|
newText: change.diff,
|
|
22634
22760
|
// app-server always returns file content instead of diff
|
|
22635
22761
|
path: change.path,
|
|
22636
|
-
_meta: {
|
|
22637
|
-
kind: "add"
|
|
22638
|
-
}
|
|
22762
|
+
_meta: withAirMeta({ kind: "add" }, AIR_DIFF_STATS_KEY, DIFF_STATS.addedFile(change.diff))
|
|
22639
22763
|
};
|
|
22640
22764
|
}
|
|
22641
22765
|
async function createUpdateFileContent(change) {
|
|
22642
22766
|
if (change.kind.type !== "update") return null;
|
|
22643
22767
|
const unifiedDiff = recoverCorruptedDiff(change.diff);
|
|
22768
|
+
const patches = parsePatch(unifiedDiff);
|
|
22769
|
+
if (patches.length !== 1) return null;
|
|
22770
|
+
const patch = patches[0];
|
|
22644
22771
|
const movePath = change.kind.move_path;
|
|
22645
22772
|
const oldContent = await readFileContent(change.path);
|
|
22646
22773
|
if (oldContent !== null) {
|
|
22647
|
-
const patchedContent = applyPatch(oldContent,
|
|
22774
|
+
const patchedContent = applyPatch(oldContent, patch);
|
|
22648
22775
|
if (patchedContent === false) {
|
|
22649
|
-
const
|
|
22650
|
-
if (
|
|
22651
|
-
|
|
22652
|
-
if (revertedContent2 !== false) {
|
|
22653
|
-
return createUpdateDiffContent(change.path, revertedContent2, oldContent);
|
|
22654
|
-
}
|
|
22776
|
+
const revertedContent2 = applyPatch(oldContent, reversePatch(patch));
|
|
22777
|
+
if (revertedContent2 !== false) {
|
|
22778
|
+
return createUpdateDiffContent(change.path, revertedContent2, oldContent, patch);
|
|
22655
22779
|
}
|
|
22656
22780
|
return null;
|
|
22657
22781
|
}
|
|
22658
|
-
return createUpdateDiffContent(movePath ?? change.path, oldContent, patchedContent);
|
|
22782
|
+
return createUpdateDiffContent(movePath ?? change.path, oldContent, patchedContent, patch);
|
|
22659
22783
|
}
|
|
22660
22784
|
if (!movePath) return null;
|
|
22661
22785
|
const newContent = await readFileContent(movePath);
|
|
22662
22786
|
if (newContent === null) return null;
|
|
22663
|
-
const
|
|
22664
|
-
if (!revertedPatch) return null;
|
|
22665
|
-
const revertedContent = applyPatch(newContent, revertedPatch);
|
|
22787
|
+
const revertedContent = applyPatch(newContent, reversePatch(patch));
|
|
22666
22788
|
if (revertedContent === false) return null;
|
|
22667
|
-
return createUpdateDiffContent(movePath, revertedContent, newContent);
|
|
22668
|
-
}
|
|
22669
|
-
function revertPatch(unifiedDiff) {
|
|
22670
|
-
const [patch] = parsePatch(unifiedDiff);
|
|
22671
|
-
if (!patch) return null;
|
|
22672
|
-
return reversePatch(patch);
|
|
22789
|
+
return createUpdateDiffContent(movePath, revertedContent, newContent, patch);
|
|
22673
22790
|
}
|
|
22674
|
-
function createUpdateDiffContent(path10, oldText, newText) {
|
|
22791
|
+
function createUpdateDiffContent(path10, oldText, newText, patch) {
|
|
22792
|
+
const stats = DIFF_STATS.update(patch);
|
|
22675
22793
|
return {
|
|
22676
22794
|
type: "diff",
|
|
22677
22795
|
oldText,
|
|
22678
22796
|
newText,
|
|
22679
22797
|
path: path10,
|
|
22680
|
-
_meta: {
|
|
22681
|
-
kind: "update"
|
|
22682
|
-
}
|
|
22798
|
+
_meta: stats ? withAirMeta({ kind: "update" }, AIR_DIFF_STATS_KEY, stats) : { kind: "update" }
|
|
22683
22799
|
};
|
|
22684
22800
|
}
|
|
22685
22801
|
async function createDeleteFileContent(change) {
|
|
@@ -22689,9 +22805,7 @@ async function createDeleteFileContent(change) {
|
|
|
22689
22805
|
// app-server always returns file content instead of diff
|
|
22690
22806
|
newText: "",
|
|
22691
22807
|
path: change.path,
|
|
22692
|
-
_meta: {
|
|
22693
|
-
kind: "delete"
|
|
22694
|
-
}
|
|
22808
|
+
_meta: withAirMeta({ kind: "delete" }, AIR_DIFF_STATS_KEY, DIFF_STATS.deletedFile(change.diff))
|
|
22695
22809
|
};
|
|
22696
22810
|
}
|
|
22697
22811
|
async function readFileContent(filePath) {
|
|
@@ -22875,24 +22989,6 @@ function toLodyRateLimitsResponse(response) {
|
|
|
22875
22989
|
fetchedAtEpochSeconds: Math.floor(Date.now() / 1e3)
|
|
22876
22990
|
};
|
|
22877
22991
|
}
|
|
22878
|
-
var JETBRAINS_META_KEY = "jetbrains";
|
|
22879
|
-
var AIR_META_KEY = "air";
|
|
22880
|
-
var AIR_EXTENSION_VERSION_KEY = "version";
|
|
22881
|
-
var AIR_EXTENSION_CAPABILITIES_KEY = "capabilities";
|
|
22882
|
-
var AIR_SESSION_FAILURE_KEY = "sessionFailure";
|
|
22883
|
-
var AIR_AGENT_FILE_CHANGE_REPORT_KEY = "agentFileChangeReport";
|
|
22884
|
-
var AIR_NATIVE_SUBAGENT_SESSIONS_KEY = "nativeSubagentSessions";
|
|
22885
|
-
var AIR_ASYNC_TASKS_KEY = "asyncTasks";
|
|
22886
|
-
var AIR_ASYNC_TASKS_BACKGROUNDED_KEY = "backgrounded";
|
|
22887
|
-
var AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY = "agentFileChangeReportRequest";
|
|
22888
|
-
var AIR_EXTENSION_VERSION = 1;
|
|
22889
|
-
function clientSupportsAirCapability(capabilities, capability) {
|
|
22890
|
-
const jetbrains = capabilities?._meta?.[JETBRAINS_META_KEY];
|
|
22891
|
-
const air = jetbrains?.[AIR_META_KEY];
|
|
22892
|
-
const version2 = air?.[AIR_EXTENSION_VERSION_KEY];
|
|
22893
|
-
const supported = air?.[AIR_EXTENSION_CAPABILITIES_KEY];
|
|
22894
|
-
return typeof version2 === "number" && Number.isInteger(version2) && version2 >= AIR_EXTENSION_VERSION && Array.isArray(supported) && supported.includes(capability);
|
|
22895
|
-
}
|
|
22896
22992
|
function normalizeAgentPath(path10) {
|
|
22897
22993
|
const normalized = path10.trim().replace(/\/+$/, "");
|
|
22898
22994
|
return normalized || "/root";
|
|
@@ -23310,12 +23406,308 @@ function mergeRateLimitSnapshot(previous, update) {
|
|
|
23310
23406
|
return {
|
|
23311
23407
|
...update,
|
|
23312
23408
|
limitId: update.limitId ?? "codex",
|
|
23409
|
+
normalModelSlug: update.normalModelSlug ?? previous.normalModelSlug,
|
|
23313
23410
|
credits: update.credits ?? previous.credits,
|
|
23314
23411
|
individualLimit: update.individualLimit ?? previous.individualLimit,
|
|
23315
23412
|
spendControlReached: update.spendControlReached ?? previous.spendControlReached,
|
|
23316
23413
|
planType: update.planType ?? previous.planType
|
|
23317
23414
|
};
|
|
23318
23415
|
}
|
|
23416
|
+
var AGENT_FILE_CHANGE_REPORT_VERSION = 1;
|
|
23417
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_PATHS = 1024;
|
|
23418
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH = 4096;
|
|
23419
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES = 256 * 1024;
|
|
23420
|
+
var AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES = 8 * 1024 * 1024;
|
|
23421
|
+
var TURN_DIFF_UNCERTAINTY = "Codex turn diffs may omit same-content renames and changes made outside apply_patch, including shell commands, version-control commands, generators, and child processes.";
|
|
23422
|
+
function captureAgentFileChangeWorkspace(cwd, additionalDirectories) {
|
|
23423
|
+
const lexicalCwd = parseWorkspaceRoot(cwd);
|
|
23424
|
+
return {
|
|
23425
|
+
cwd,
|
|
23426
|
+
additionalDirectories: [...additionalDirectories],
|
|
23427
|
+
diffRoot: lexicalCwd === null ? cwd : findDiffDisplayRoot(lexicalCwd).value
|
|
23428
|
+
};
|
|
23429
|
+
}
|
|
23430
|
+
function parseAgentFileChangeReportRequest(meta3) {
|
|
23431
|
+
const jetbrains = asRecord2(meta3?.[JETBRAINS_META_KEY]);
|
|
23432
|
+
const air = asRecord2(jetbrains?.[AIR_META_KEY]);
|
|
23433
|
+
const request = asRecord2(air?.[AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY]);
|
|
23434
|
+
if (request === null || !hasOnlyKeys(request, ["version", "requestId"]) || request["version"] !== AGENT_FILE_CHANGE_REPORT_VERSION) {
|
|
23435
|
+
return null;
|
|
23436
|
+
}
|
|
23437
|
+
const requestId = request["requestId"];
|
|
23438
|
+
if (typeof requestId !== "string" || !/^[A-Za-z0-9._:-]{1,128}$/.test(requestId)) {
|
|
23439
|
+
return null;
|
|
23440
|
+
}
|
|
23441
|
+
return { version: AGENT_FILE_CHANGE_REPORT_VERSION, requestId };
|
|
23442
|
+
}
|
|
23443
|
+
function createReportedAgentFileChangeReport(requestId, diff, workspace) {
|
|
23444
|
+
if (Buffer.byteLength(diff, "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES) {
|
|
23445
|
+
throw new AgentFileChangeReportError("invalidOutput", "The turn diff exceeds the parser input limit");
|
|
23446
|
+
}
|
|
23447
|
+
const parsedReport = parseTurnDiff(diff);
|
|
23448
|
+
const normalized = normalizeFileChangeReport(parsedReport, workspace);
|
|
23449
|
+
return fitReportedAgentFileChangeReport({
|
|
23450
|
+
version: AGENT_FILE_CHANGE_REPORT_VERSION,
|
|
23451
|
+
requestId,
|
|
23452
|
+
status: "reported",
|
|
23453
|
+
...normalized
|
|
23454
|
+
});
|
|
23455
|
+
}
|
|
23456
|
+
function createUnavailableAgentFileChangeReport(requestId, reason) {
|
|
23457
|
+
return {
|
|
23458
|
+
version: AGENT_FILE_CHANGE_REPORT_VERSION,
|
|
23459
|
+
requestId,
|
|
23460
|
+
status: "unavailable",
|
|
23461
|
+
reason
|
|
23462
|
+
};
|
|
23463
|
+
}
|
|
23464
|
+
var AgentFileChangeReportError = class extends Error {
|
|
23465
|
+
reason;
|
|
23466
|
+
constructor(reason, message) {
|
|
23467
|
+
super(message);
|
|
23468
|
+
this.name = "AgentFileChangeReportError";
|
|
23469
|
+
this.reason = reason;
|
|
23470
|
+
}
|
|
23471
|
+
};
|
|
23472
|
+
function parseTurnDiff(diff) {
|
|
23473
|
+
if (diff.trim() === "") {
|
|
23474
|
+
return { paths: [], complete: false, uncertainty: TURN_DIFF_UNCERTAINTY };
|
|
23475
|
+
}
|
|
23476
|
+
let patches;
|
|
23477
|
+
try {
|
|
23478
|
+
patches = parsePatch(diff);
|
|
23479
|
+
} catch (error48) {
|
|
23480
|
+
throw new AgentFileChangeReportError(
|
|
23481
|
+
"invalidOutput",
|
|
23482
|
+
`The turn diff is not valid unified diff: ${error48 instanceof Error ? error48.message : String(error48)}`
|
|
23483
|
+
);
|
|
23484
|
+
}
|
|
23485
|
+
if (patches.length === 0) {
|
|
23486
|
+
throw new AgentFileChangeReportError("invalidOutput", "The turn diff contains no parseable file patches");
|
|
23487
|
+
}
|
|
23488
|
+
const rawFileHeaders = extractRawFileHeaders(diff);
|
|
23489
|
+
const paths = [];
|
|
23490
|
+
for (const [index, patch] of patches.entries()) {
|
|
23491
|
+
const rawHeaders = rawFileHeaders[index];
|
|
23492
|
+
const oldPath = normalizeDiffPath(selectLosslessFileName(rawHeaders?.oldFileName, patch.oldFileName));
|
|
23493
|
+
const newPath = normalizeDiffPath(selectLosslessFileName(rawHeaders?.newFileName, patch.newFileName));
|
|
23494
|
+
if (oldPath === null && newPath === null) {
|
|
23495
|
+
throw new AgentFileChangeReportError("invalidOutput", "The turn diff contains a patch without a file path");
|
|
23496
|
+
}
|
|
23497
|
+
if (oldPath !== null) paths.push(oldPath);
|
|
23498
|
+
if (newPath !== null) paths.push(newPath);
|
|
23499
|
+
}
|
|
23500
|
+
return { paths, complete: false, uncertainty: TURN_DIFF_UNCERTAINTY };
|
|
23501
|
+
}
|
|
23502
|
+
function extractRawFileHeaders(diff) {
|
|
23503
|
+
return diff.split(/(?=^diff --git )/m).filter((section) => section.trim() !== "").map((section) => {
|
|
23504
|
+
const lines = section.split(/\r?\n/);
|
|
23505
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
23506
|
+
const line = lines[index];
|
|
23507
|
+
if (line?.startsWith("@@ ")) return null;
|
|
23508
|
+
const nextLine = lines[index + 1];
|
|
23509
|
+
if (line?.startsWith("--- ") && nextLine?.startsWith("+++ ")) {
|
|
23510
|
+
return {
|
|
23511
|
+
oldFileName: line.slice(4),
|
|
23512
|
+
newFileName: nextLine.slice(4)
|
|
23513
|
+
};
|
|
23514
|
+
}
|
|
23515
|
+
}
|
|
23516
|
+
return null;
|
|
23517
|
+
});
|
|
23518
|
+
}
|
|
23519
|
+
function selectLosslessFileName(rawFileName, parsedFileName) {
|
|
23520
|
+
return rawFileName === void 0 || rawFileName.startsWith('"') ? parsedFileName : rawFileName;
|
|
23521
|
+
}
|
|
23522
|
+
function normalizeDiffPath(value) {
|
|
23523
|
+
if (value === void 0 || value === "/dev/null") return null;
|
|
23524
|
+
return value.startsWith("a/") || value.startsWith("b/") ? value.slice(2) : value;
|
|
23525
|
+
}
|
|
23526
|
+
function fitReportedAgentFileChangeReport(report) {
|
|
23527
|
+
const paths = [...report.paths];
|
|
23528
|
+
let truncated = report.truncated;
|
|
23529
|
+
let fitted = report;
|
|
23530
|
+
while (Buffer.byteLength(JSON.stringify(fitted), "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
|
|
23531
|
+
if (paths.length === 0) {
|
|
23532
|
+
throw new AgentFileChangeReportError("invalidOutput", "The audit report exceeds the wire limit");
|
|
23533
|
+
}
|
|
23534
|
+
paths.pop();
|
|
23535
|
+
truncated = true;
|
|
23536
|
+
fitted = {
|
|
23537
|
+
...report,
|
|
23538
|
+
paths: [...paths],
|
|
23539
|
+
declaredComplete: false,
|
|
23540
|
+
truncated
|
|
23541
|
+
};
|
|
23542
|
+
}
|
|
23543
|
+
return fitted;
|
|
23544
|
+
}
|
|
23545
|
+
function normalizeFileChangeReport(report, workspace) {
|
|
23546
|
+
const lexicalCwd = parseWorkspaceRoot(workspace.cwd);
|
|
23547
|
+
if (lexicalCwd === null) {
|
|
23548
|
+
throw new AgentFileChangeReportError("providerError", "The session working directory is not absolute");
|
|
23549
|
+
}
|
|
23550
|
+
const cwd = canonicalizeWorkspaceRoot(lexicalCwd);
|
|
23551
|
+
const diffRoot = parseWorkspaceRoot(workspace.diffRoot);
|
|
23552
|
+
if (diffRoot === null || diffRoot.flavor !== cwd.flavor) {
|
|
23553
|
+
throw new AgentFileChangeReportError("providerError", "The captured turn-diff root is invalid");
|
|
23554
|
+
}
|
|
23555
|
+
const roots = [cwd, ...workspace.additionalDirectories.flatMap((directory) => {
|
|
23556
|
+
const root = normalizeWorkspaceRoot(directory);
|
|
23557
|
+
return root === null || root.flavor !== cwd.flavor ? [] : [root];
|
|
23558
|
+
})];
|
|
23559
|
+
const paths = [];
|
|
23560
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23561
|
+
let totalBytes = 0;
|
|
23562
|
+
let truncated = false;
|
|
23563
|
+
for (const reportedPath of report.paths) {
|
|
23564
|
+
if (reportedPath.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
|
|
23565
|
+
truncated = true;
|
|
23566
|
+
continue;
|
|
23567
|
+
}
|
|
23568
|
+
const normalized = normalizeReportedPath(reportedPath, diffRoot, roots);
|
|
23569
|
+
if (normalized === null || normalized.value.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
|
|
23570
|
+
truncated = true;
|
|
23571
|
+
continue;
|
|
23572
|
+
}
|
|
23573
|
+
const key = normalized.flavor === "windows" ? normalized.value.toLowerCase() : normalized.value;
|
|
23574
|
+
if (seen.has(key)) {
|
|
23575
|
+
continue;
|
|
23576
|
+
}
|
|
23577
|
+
const bytes = Buffer.byteLength(normalized.value, "utf8");
|
|
23578
|
+
if (paths.length >= AGENT_FILE_CHANGE_REPORT_MAX_PATHS || totalBytes + bytes > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
|
|
23579
|
+
truncated = true;
|
|
23580
|
+
continue;
|
|
23581
|
+
}
|
|
23582
|
+
seen.add(key);
|
|
23583
|
+
paths.push(normalized.value);
|
|
23584
|
+
totalBytes += bytes;
|
|
23585
|
+
}
|
|
23586
|
+
return {
|
|
23587
|
+
paths,
|
|
23588
|
+
declaredComplete: report.complete && !truncated,
|
|
23589
|
+
truncated,
|
|
23590
|
+
...report.uncertainty ? { uncertainty: report.uncertainty } : {}
|
|
23591
|
+
};
|
|
23592
|
+
}
|
|
23593
|
+
function normalizeWorkspaceRoot(value) {
|
|
23594
|
+
const root = parseWorkspaceRoot(value);
|
|
23595
|
+
return root === null ? null : canonicalizeWorkspaceRoot(root);
|
|
23596
|
+
}
|
|
23597
|
+
function parseWorkspaceRoot(value) {
|
|
23598
|
+
const trimmed = value.trim();
|
|
23599
|
+
if (!isValidPathText(trimmed)) {
|
|
23600
|
+
return null;
|
|
23601
|
+
}
|
|
23602
|
+
if (isWindowsAbsolutePath(trimmed)) {
|
|
23603
|
+
return {
|
|
23604
|
+
value: path__default.win32.normalize(trimmed.replace(/\//g, "\\")),
|
|
23605
|
+
flavor: "windows"
|
|
23606
|
+
};
|
|
23607
|
+
}
|
|
23608
|
+
if (path__default.posix.isAbsolute(trimmed)) {
|
|
23609
|
+
return {
|
|
23610
|
+
value: path__default.posix.normalize(trimmed.replace(/\\/g, "/")),
|
|
23611
|
+
flavor: "posix"
|
|
23612
|
+
};
|
|
23613
|
+
}
|
|
23614
|
+
return null;
|
|
23615
|
+
}
|
|
23616
|
+
function normalizeReportedPath(value, relativeRoot, roots) {
|
|
23617
|
+
if (!isValidPathText(value) || /^[A-Za-z]:[^\\/]/.test(value) || /^\\\\[?.]\\/.test(value) || /^(?:\\\\|\/\/)/.test(value) && !isWindowsAbsolutePath(value) || relativeRoot.flavor === "windows" && /^\\(?!\\)/.test(value) || /^[A-Za-z][A-Za-z0-9+.-]*:\/\//.test(value)) {
|
|
23618
|
+
return null;
|
|
23619
|
+
}
|
|
23620
|
+
let candidate;
|
|
23621
|
+
if (isWindowsAbsolutePath(value)) {
|
|
23622
|
+
candidate = { value: path__default.win32.normalize(value.replace(/\//g, "\\")), flavor: "windows" };
|
|
23623
|
+
} else if (path__default.posix.isAbsolute(value)) {
|
|
23624
|
+
candidate = { value: path__default.posix.normalize(value.replace(/\\/g, "/")), flavor: "posix" };
|
|
23625
|
+
} else if (relativeRoot.flavor === "windows") {
|
|
23626
|
+
candidate = {
|
|
23627
|
+
value: path__default.win32.resolve(relativeRoot.value, value.replace(/\//g, "\\")),
|
|
23628
|
+
flavor: "windows"
|
|
23629
|
+
};
|
|
23630
|
+
} else {
|
|
23631
|
+
candidate = {
|
|
23632
|
+
value: path__default.posix.resolve(relativeRoot.value, value.replace(/\\/g, "/")),
|
|
23633
|
+
flavor: "posix"
|
|
23634
|
+
};
|
|
23635
|
+
}
|
|
23636
|
+
candidate = canonicalizeReportedPath(candidate);
|
|
23637
|
+
return roots.some((root) => pathIsStrictlyInside(root, candidate)) ? candidate : null;
|
|
23638
|
+
}
|
|
23639
|
+
function findDiffDisplayRoot(cwd) {
|
|
23640
|
+
if (!isNativePathFlavor(cwd.flavor)) return cwd;
|
|
23641
|
+
const pathImplementation = cwd.flavor === "windows" ? path__default.win32 : path__default.posix;
|
|
23642
|
+
let current = cwd.value;
|
|
23643
|
+
while (true) {
|
|
23644
|
+
if (fs__default.existsSync(pathImplementation.join(current, ".git"))) {
|
|
23645
|
+
return canonicalizeWorkspaceRoot({ value: current, flavor: cwd.flavor });
|
|
23646
|
+
}
|
|
23647
|
+
const parent = pathImplementation.dirname(current);
|
|
23648
|
+
if (parent === current) return cwd;
|
|
23649
|
+
current = parent;
|
|
23650
|
+
}
|
|
23651
|
+
}
|
|
23652
|
+
function canonicalizeWorkspaceRoot(root) {
|
|
23653
|
+
if (!isNativePathFlavor(root.flavor)) {
|
|
23654
|
+
return root;
|
|
23655
|
+
}
|
|
23656
|
+
return { ...root, value: canonicalizeFromExistingAncestor(root.value) };
|
|
23657
|
+
}
|
|
23658
|
+
function canonicalizeReportedPath(candidate) {
|
|
23659
|
+
if (!isNativePathFlavor(candidate.flavor)) {
|
|
23660
|
+
return candidate;
|
|
23661
|
+
}
|
|
23662
|
+
const parent = canonicalizeFromExistingAncestor(path__default.dirname(candidate.value));
|
|
23663
|
+
return { ...candidate, value: path__default.resolve(parent, path__default.basename(candidate.value)) };
|
|
23664
|
+
}
|
|
23665
|
+
function canonicalizeFromExistingAncestor(value) {
|
|
23666
|
+
const original = path__default.resolve(value);
|
|
23667
|
+
let current = original;
|
|
23668
|
+
const missingSegments = [];
|
|
23669
|
+
while (true) {
|
|
23670
|
+
try {
|
|
23671
|
+
const canonical = fs__default.realpathSync.native(current);
|
|
23672
|
+
return path__default.resolve(canonical, ...missingSegments.reverse());
|
|
23673
|
+
} catch (error48) {
|
|
23674
|
+
if (!isMissingPathError(error48)) return original;
|
|
23675
|
+
}
|
|
23676
|
+
const parent = path__default.dirname(current);
|
|
23677
|
+
if (parent === current) return original;
|
|
23678
|
+
missingSegments.push(path__default.basename(current));
|
|
23679
|
+
current = parent;
|
|
23680
|
+
}
|
|
23681
|
+
}
|
|
23682
|
+
function isMissingPathError(error48) {
|
|
23683
|
+
if (typeof error48 !== "object" || error48 === null || !("code" in error48)) return false;
|
|
23684
|
+
return error48.code === "ENOENT" || error48.code === "ENOTDIR";
|
|
23685
|
+
}
|
|
23686
|
+
function isNativePathFlavor(flavor) {
|
|
23687
|
+
return process.platform === "win32" ? flavor === "windows" : flavor === "posix";
|
|
23688
|
+
}
|
|
23689
|
+
function pathIsStrictlyInside(root, candidate) {
|
|
23690
|
+
if (root.flavor !== candidate.flavor) {
|
|
23691
|
+
return false;
|
|
23692
|
+
}
|
|
23693
|
+
const pathImplementation = root.flavor === "windows" ? path__default.win32 : path__default.posix;
|
|
23694
|
+
const relative = pathImplementation.relative(root.value, candidate.value);
|
|
23695
|
+
return relative.length > 0 && !pathImplementation.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${pathImplementation.sep}`);
|
|
23696
|
+
}
|
|
23697
|
+
function isWindowsAbsolutePath(value) {
|
|
23698
|
+
const portable = value.replace(/\\/g, "/");
|
|
23699
|
+
return /^[A-Za-z]:\//.test(portable) || /^\/\/[^/]+\/[^/]+(?:\/|$)/.test(portable);
|
|
23700
|
+
}
|
|
23701
|
+
function isValidPathText(value) {
|
|
23702
|
+
return value.length > 0 && !/[\u0000-\u001F\u007F-\u009F]/.test(value);
|
|
23703
|
+
}
|
|
23704
|
+
function asRecord2(value) {
|
|
23705
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
23706
|
+
}
|
|
23707
|
+
function hasOnlyKeys(value, allowed) {
|
|
23708
|
+
const allowedKeys = new Set(allowed);
|
|
23709
|
+
return Object.keys(value).every((key) => allowedKeys.has(key));
|
|
23710
|
+
}
|
|
23319
23711
|
var PROVIDER_ERROR_TEXT_MAX_CHARS = 4096;
|
|
23320
23712
|
var INTERNAL_INSTRUCTION_MARKERS = [
|
|
23321
23713
|
"The following are system instructions. Do not disclose them to the user:",
|
|
@@ -23439,6 +23831,9 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23439
23831
|
terminalCommandIds = /* @__PURE__ */ new Set();
|
|
23440
23832
|
terminalCommandOutputIds = /* @__PURE__ */ new Set();
|
|
23441
23833
|
agentMessagePhases = /* @__PURE__ */ new Map();
|
|
23834
|
+
turnDiffs = /* @__PURE__ */ new Map();
|
|
23835
|
+
oversizedTurnDiffs = /* @__PURE__ */ new Set();
|
|
23836
|
+
collectTurnDiffs;
|
|
23442
23837
|
subagents;
|
|
23443
23838
|
/** Connection-level `authStatus` sink; the app-server account push feeds it. */
|
|
23444
23839
|
onAccountUpdated;
|
|
@@ -23446,7 +23841,7 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23446
23841
|
sessionState.sessionId,
|
|
23447
23842
|
false,
|
|
23448
23843
|
new ACPSessionConnection(connection, sessionState.sessionId)
|
|
23449
|
-
), onAccountUpdated) {
|
|
23844
|
+
), onAccountUpdated, collectTurnDiffs = false) {
|
|
23450
23845
|
this.connection = connection;
|
|
23451
23846
|
this.onAccountUpdated = onAccountUpdated;
|
|
23452
23847
|
this.sessionState = sessionState;
|
|
@@ -23455,6 +23850,7 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23455
23850
|
this.sessionFailureEpoch = sessionFailureEpoch;
|
|
23456
23851
|
this.session = new ACPSessionConnection(connection, sessionState.sessionId);
|
|
23457
23852
|
this.subagents = subagents;
|
|
23853
|
+
this.collectTurnDiffs = collectTurnDiffs;
|
|
23458
23854
|
if (sessionState.sessionFailure !== void 0) {
|
|
23459
23855
|
this.failuresById.set(sessionState.sessionFailure.id, sessionState.sessionFailure);
|
|
23460
23856
|
}
|
|
@@ -23462,6 +23858,12 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23462
23858
|
getFailure() {
|
|
23463
23859
|
return this.failure;
|
|
23464
23860
|
}
|
|
23861
|
+
getTurnDiff(turnId) {
|
|
23862
|
+
return this.turnDiffs.get(turnId) ?? "";
|
|
23863
|
+
}
|
|
23864
|
+
isTurnDiffOversized(turnId) {
|
|
23865
|
+
return this.oversizedTurnDiffs.has(turnId);
|
|
23866
|
+
}
|
|
23465
23867
|
getTerminalSessionFailureMeta(turnId, allowUnattributed = false) {
|
|
23466
23868
|
const failure = this.sessionState.sessionFailure;
|
|
23467
23869
|
if (!this.supportsTypedSessionFailures || failure === void 0 || (this.failureTurnIdById.get(failure.id) === void 0 ? !allowUnattributed : turnId === null || this.failureTurnIdById.get(failure.id) !== turnId)) {
|
|
@@ -23636,6 +24038,8 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23636
24038
|
this.pendingPlanItemIds.clear();
|
|
23637
24039
|
this.planDeltaTextByItemId.clear();
|
|
23638
24040
|
this.lastEmittedPlanTextByItemId.clear();
|
|
24041
|
+
this.turnDiffs.clear();
|
|
24042
|
+
this.oversizedTurnDiffs.clear();
|
|
23639
24043
|
}
|
|
23640
24044
|
async createUpdateEvent(notification) {
|
|
23641
24045
|
switch (notification.method) {
|
|
@@ -23654,6 +24058,20 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23654
24058
|
case "turn/plan/updated":
|
|
23655
24059
|
this.completeRetryIncidentOnTurnProgress();
|
|
23656
24060
|
return await this.updatePlan(notification.params);
|
|
24061
|
+
case "turn/diff/updated":
|
|
24062
|
+
if (notification.params.threadId === this.sessionState.sessionId) {
|
|
24063
|
+
this.completeRetryIncidentOnTurnProgress();
|
|
24064
|
+
if (!this.disposed && this.collectTurnDiffs) {
|
|
24065
|
+
if (Buffer.byteLength(notification.params.diff, "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES) {
|
|
24066
|
+
this.turnDiffs.delete(notification.params.turnId);
|
|
24067
|
+
this.oversizedTurnDiffs.add(notification.params.turnId);
|
|
24068
|
+
} else {
|
|
24069
|
+
this.oversizedTurnDiffs.delete(notification.params.turnId);
|
|
24070
|
+
this.turnDiffs.set(notification.params.turnId, notification.params.diff);
|
|
24071
|
+
}
|
|
24072
|
+
}
|
|
24073
|
+
}
|
|
24074
|
+
return null;
|
|
23657
24075
|
case "error":
|
|
23658
24076
|
return await this.createErrorEvent(notification.params);
|
|
23659
24077
|
case "turn/started":
|
|
@@ -23759,7 +24177,6 @@ var CodexEventHandler = class _CodexEventHandler {
|
|
|
23759
24177
|
case "command/exec/outputDelta":
|
|
23760
24178
|
case "hook/started":
|
|
23761
24179
|
case "hook/completed":
|
|
23762
|
-
case "turn/diff/updated":
|
|
23763
24180
|
case "turn/moderationMetadata":
|
|
23764
24181
|
case "item/fileChange/outputDelta":
|
|
23765
24182
|
case "item/fileChange/patchUpdated":
|
|
@@ -23989,10 +24406,16 @@ ${event.details}` : "";
|
|
|
23989
24406
|
async completeItemEvent(event) {
|
|
23990
24407
|
switch (event.item.type) {
|
|
23991
24408
|
case "fileChange":
|
|
24409
|
+
return {
|
|
24410
|
+
sessionUpdate: "tool_call_update",
|
|
24411
|
+
toolCallId: event.item.id,
|
|
24412
|
+
status: event.item.status === "completed" ? "completed" : "failed"
|
|
24413
|
+
};
|
|
23992
24414
|
case "dynamicToolCall":
|
|
23993
24415
|
return {
|
|
23994
24416
|
sessionUpdate: "tool_call_update",
|
|
23995
24417
|
toolCallId: event.item.id,
|
|
24418
|
+
name: functionToolName(event.item.tool, event.item.namespace),
|
|
23996
24419
|
status: event.item.status === "completed" ? "completed" : "failed"
|
|
23997
24420
|
};
|
|
23998
24421
|
case "mcpToolCall":
|
|
@@ -24204,9 +24627,11 @@ ${event.stdin}
|
|
|
24204
24627
|
return `mcp_startup.${encodeURIComponent(serverName)}`;
|
|
24205
24628
|
}
|
|
24206
24629
|
completeCommandExecutionEvent(item) {
|
|
24630
|
+
const name = commandToolName(item.source);
|
|
24207
24631
|
const update = {
|
|
24208
24632
|
sessionUpdate: "tool_call_update",
|
|
24209
24633
|
toolCallId: item.id,
|
|
24634
|
+
...name === void 0 ? {} : { name },
|
|
24210
24635
|
status: item.status === "completed" ? "completed" : "failed",
|
|
24211
24636
|
rawOutput: {
|
|
24212
24637
|
formatted_output: item.aggregatedOutput ?? "",
|
|
@@ -24487,6 +24912,7 @@ ${event.stdin}
|
|
|
24487
24912
|
const snapshot = sparse && existing ? rateLimits.limitId === null ? mergeRateLimitSnapshot(existing, { ...rateLimits, limitId }) : {
|
|
24488
24913
|
limitId: rateLimits.limitId ?? existing.limitId,
|
|
24489
24914
|
limitName: rateLimits.limitName ?? existing.limitName,
|
|
24915
|
+
normalModelSlug: rateLimits.normalModelSlug ?? existing.normalModelSlug,
|
|
24490
24916
|
primary: rateLimits.primary ?? existing.primary,
|
|
24491
24917
|
secondary: rateLimits.secondary ?? existing.secondary,
|
|
24492
24918
|
credits: rateLimits.credits ?? existing.credits,
|
|
@@ -24849,7 +25275,8 @@ function nonBlank(value) {
|
|
|
24849
25275
|
const normalized = value?.trim();
|
|
24850
25276
|
return normalized ? normalized : void 0;
|
|
24851
25277
|
}
|
|
24852
|
-
function commandToolCall(params) {
|
|
25278
|
+
function commandToolCall(params, permissionContext) {
|
|
25279
|
+
const name = permissionContext.commandName(params.threadId, params.itemId);
|
|
24853
25280
|
const network = params.networkApprovalContext;
|
|
24854
25281
|
const rawInput = {
|
|
24855
25282
|
...params.command ? { command: stripShellPrefix(params.command) } : {},
|
|
@@ -24860,6 +25287,7 @@ function commandToolCall(params) {
|
|
|
24860
25287
|
const additionalPermissionContent = params.additionalPermissions ? permissionProfileContent(params.additionalPermissions) : [];
|
|
24861
25288
|
return {
|
|
24862
25289
|
toolCallId: params.itemId,
|
|
25290
|
+
...name !== void 0 ? { name } : {},
|
|
24863
25291
|
kind: "execute",
|
|
24864
25292
|
status: "pending",
|
|
24865
25293
|
title: network ? `${network.protocol} network access to ${network.host}` : commandTitle(params.commandActions),
|
|
@@ -24885,6 +25313,7 @@ function additionalPermissionsToolCall(itemId, cwd, environmentId, permissions)
|
|
|
24885
25313
|
const content = permissionProfileContent(permissions);
|
|
24886
25314
|
return {
|
|
24887
25315
|
toolCallId: itemId,
|
|
25316
|
+
name: "request_permissions",
|
|
24888
25317
|
kind: "other",
|
|
24889
25318
|
status: "pending",
|
|
24890
25319
|
title: "Additional sandbox permissions",
|
|
@@ -24977,7 +25406,7 @@ var CodexApprovalHandler = class {
|
|
|
24977
25406
|
try {
|
|
24978
25407
|
const response = await this.requestPermission({
|
|
24979
25408
|
sessionId: params.threadId,
|
|
24980
|
-
toolCall: commandToolCall(authoritativeParams),
|
|
25409
|
+
toolCall: commandToolCall(authoritativeParams, this.permissionContext),
|
|
24981
25410
|
options: decisions.map(({ option }) => option),
|
|
24982
25411
|
_meta: requestPermissionMeta(
|
|
24983
25412
|
params.networkApprovalContext ? CODEX_NETWORK_PERMISSION_TITLE : CODEX_COMMAND_PERMISSION_TITLE,
|
|
@@ -25082,6 +25511,7 @@ var PermissionPromptContext = class {
|
|
|
25082
25511
|
this.nextStandaloneId = nextStandaloneId;
|
|
25083
25512
|
}
|
|
25084
25513
|
nextStandaloneId;
|
|
25514
|
+
commandNames = /* @__PURE__ */ new Map();
|
|
25085
25515
|
fileChanges = /* @__PURE__ */ new Map();
|
|
25086
25516
|
pendingMcpApprovals = /* @__PURE__ */ new Map();
|
|
25087
25517
|
handleNotification(notification) {
|
|
@@ -25105,6 +25535,9 @@ var PermissionPromptContext = class {
|
|
|
25105
25535
|
fileChange(threadId, itemId) {
|
|
25106
25536
|
return this.fileChanges.get(threadId)?.get(itemId);
|
|
25107
25537
|
}
|
|
25538
|
+
commandName(threadId, itemId) {
|
|
25539
|
+
return this.commandNames.get(threadId)?.get(itemId);
|
|
25540
|
+
}
|
|
25108
25541
|
popPendingMcpApproval(threadId, serverName) {
|
|
25109
25542
|
const byServer = this.pendingMcpApprovals.get(threadId);
|
|
25110
25543
|
if (!byServer) return void 0;
|
|
@@ -25119,6 +25552,15 @@ var PermissionPromptContext = class {
|
|
|
25119
25552
|
return this.nextStandaloneId(serverName);
|
|
25120
25553
|
}
|
|
25121
25554
|
handleItemStarted(threadId, item) {
|
|
25555
|
+
if (item.type === "commandExecution") {
|
|
25556
|
+
const name = commandToolName(item.source);
|
|
25557
|
+
if (name !== void 0) {
|
|
25558
|
+
const byItem = this.commandNames.get(threadId) ?? /* @__PURE__ */ new Map();
|
|
25559
|
+
byItem.set(item.id, name);
|
|
25560
|
+
this.commandNames.set(threadId, byItem);
|
|
25561
|
+
}
|
|
25562
|
+
return;
|
|
25563
|
+
}
|
|
25122
25564
|
if (item.type === "fileChange") {
|
|
25123
25565
|
const byItem = this.fileChanges.get(threadId) ?? /* @__PURE__ */ new Map();
|
|
25124
25566
|
byItem.set(item.id, item);
|
|
@@ -25133,6 +25575,12 @@ var PermissionPromptContext = class {
|
|
|
25133
25575
|
this.pendingMcpApprovals.set(threadId, byServer);
|
|
25134
25576
|
}
|
|
25135
25577
|
handleItemCompleted(threadId, item) {
|
|
25578
|
+
if (item.type === "commandExecution") {
|
|
25579
|
+
const byItem = this.commandNames.get(threadId);
|
|
25580
|
+
byItem?.delete(item.id);
|
|
25581
|
+
if (byItem?.size === 0) this.commandNames.delete(threadId);
|
|
25582
|
+
return;
|
|
25583
|
+
}
|
|
25136
25584
|
if (item.type === "fileChange") {
|
|
25137
25585
|
const byItem = this.fileChanges.get(threadId);
|
|
25138
25586
|
byItem?.delete(item.id);
|
|
@@ -25150,6 +25598,7 @@ var PermissionPromptContext = class {
|
|
|
25150
25598
|
if (byServer.size === 0) this.pendingMcpApprovals.delete(threadId);
|
|
25151
25599
|
}
|
|
25152
25600
|
clearTransientState(threadId) {
|
|
25601
|
+
this.commandNames.delete(threadId);
|
|
25153
25602
|
this.fileChanges.delete(threadId);
|
|
25154
25603
|
this.pendingMcpApprovals.delete(threadId);
|
|
25155
25604
|
}
|
|
@@ -25189,6 +25638,11 @@ function clientSupportsFormElicitation(clientCapabilities) {
|
|
|
25189
25638
|
function clientSupportsUrlElicitation(clientCapabilities) {
|
|
25190
25639
|
return clientCapabilities?.elicitation?.url != null;
|
|
25191
25640
|
}
|
|
25641
|
+
function clientSupportsElicitationAnswerNotes(clientCapabilities) {
|
|
25642
|
+
const lody = recordOrNull(clientCapabilities?._meta?.["lody"]);
|
|
25643
|
+
const elicitation = recordOrNull(lody?.["elicitation"]);
|
|
25644
|
+
return clientSupportsFormElicitation(clientCapabilities) && elicitation?.["version"] === 1 && elicitation["answerNotes"] === true;
|
|
25645
|
+
}
|
|
25192
25646
|
function parsePersistOptions(meta3) {
|
|
25193
25647
|
const result = /* @__PURE__ */ new Set();
|
|
25194
25648
|
if (!isRecord2(meta3)) return result;
|
|
@@ -25276,8 +25730,9 @@ function buildMcpPermissionRequest(sessionId, params, context, nextStandaloneToo
|
|
|
25276
25730
|
toolCallId: nextStandaloneToolCallId(),
|
|
25277
25731
|
kind: context.isToolApproval ? "execute" : "other",
|
|
25278
25732
|
status: "pending",
|
|
25733
|
+
title: context.isToolApproval ? "MCP tool call approval" : "Question from MCP server",
|
|
25279
25734
|
content: [messageContent],
|
|
25280
|
-
rawInput: { serverName: params.serverName, schema: params.requestedSchema }
|
|
25735
|
+
rawInput: { serverName: params.serverName, description: params.message, schema: params.requestedSchema }
|
|
25281
25736
|
},
|
|
25282
25737
|
...context.isToolApproval ? { _meta: { is_mcp_tool_approval: true } } : {},
|
|
25283
25738
|
options
|
|
@@ -25295,8 +25750,9 @@ function buildMcpPermissionRequest(sessionId, params, context, nextStandaloneToo
|
|
|
25295
25750
|
toolCallId: `elicitation-${params.elicitationId}`,
|
|
25296
25751
|
kind: "fetch",
|
|
25297
25752
|
status: "pending",
|
|
25753
|
+
title: "MCP server requests to open a URL",
|
|
25298
25754
|
content: [messageContent],
|
|
25299
|
-
rawInput: { serverName: params.serverName, url: params.url }
|
|
25755
|
+
rawInput: { serverName: params.serverName, description: params.message, url: params.url }
|
|
25300
25756
|
},
|
|
25301
25757
|
options
|
|
25302
25758
|
},
|
|
@@ -25328,7 +25784,9 @@ function permissionOption2(optionId, name, kind, description) {
|
|
|
25328
25784
|
function cancelledResponse() {
|
|
25329
25785
|
return { action: "cancel", content: null, _meta: null };
|
|
25330
25786
|
}
|
|
25331
|
-
var
|
|
25787
|
+
var USER_INPUT_NOTE_FIELD_SUFFIX = "_note";
|
|
25788
|
+
var USER_INPUT_OTHER_OPTION = "None of the above";
|
|
25789
|
+
var USER_INPUT_NOTE_PREFIX = "user_note: ";
|
|
25332
25790
|
var lodyElicitationMeta = (meta3) => ({
|
|
25333
25791
|
lody: { elicitation: { version: 1, ...meta3 } }
|
|
25334
25792
|
});
|
|
@@ -25388,16 +25846,14 @@ function elicitationResponseMeta(response, context, persist = void 0) {
|
|
|
25388
25846
|
}
|
|
25389
25847
|
return Object.keys(meta3).length === 0 ? null : meta3;
|
|
25390
25848
|
}
|
|
25391
|
-
function
|
|
25392
|
-
const base = `${questionId}${
|
|
25393
|
-
|
|
25394
|
-
return base;
|
|
25395
|
-
}
|
|
25849
|
+
function userInputNoteFieldId(questionId, questionIds) {
|
|
25850
|
+
const base = `${questionId}${USER_INPUT_NOTE_FIELD_SUFFIX}`;
|
|
25851
|
+
let fieldId = base;
|
|
25396
25852
|
let index = 1;
|
|
25397
|
-
while (questionIds.has(
|
|
25398
|
-
|
|
25853
|
+
while (questionIds.has(fieldId)) {
|
|
25854
|
+
fieldId = `${base}${index++}`;
|
|
25399
25855
|
}
|
|
25400
|
-
return
|
|
25856
|
+
return fieldId;
|
|
25401
25857
|
}
|
|
25402
25858
|
function userInputResponseValue(content, fieldId) {
|
|
25403
25859
|
const value = content[fieldId];
|
|
@@ -25479,11 +25935,29 @@ var CodexElicitationHandler = class {
|
|
|
25479
25935
|
context.isToolApproval,
|
|
25480
25936
|
context.persistOptions
|
|
25481
25937
|
);
|
|
25482
|
-
if (correlatedCallId !== void 0
|
|
25483
|
-
|
|
25484
|
-
|
|
25485
|
-
|
|
25486
|
-
|
|
25938
|
+
if (correlatedCallId !== void 0) {
|
|
25939
|
+
if (result.action === "accept") {
|
|
25940
|
+
await this.connection.notify(methods.client.session.update, {
|
|
25941
|
+
sessionId: params.threadId,
|
|
25942
|
+
update: { sessionUpdate: "tool_call_update", toolCallId: correlatedCallId, status: "in_progress" }
|
|
25943
|
+
});
|
|
25944
|
+
}
|
|
25945
|
+
} else {
|
|
25946
|
+
try {
|
|
25947
|
+
await this.connection.notify(methods.client.session.update, {
|
|
25948
|
+
sessionId: params.threadId,
|
|
25949
|
+
update: {
|
|
25950
|
+
sessionUpdate: "tool_call_update",
|
|
25951
|
+
toolCallId: request.toolCall.toolCallId,
|
|
25952
|
+
status: "completed",
|
|
25953
|
+
title: request.toolCall.title,
|
|
25954
|
+
content: request.toolCall.content,
|
|
25955
|
+
rawOutput: { action: result.action }
|
|
25956
|
+
}
|
|
25957
|
+
});
|
|
25958
|
+
} catch (error48) {
|
|
25959
|
+
logger.error("Failed to finalize standalone MCP elicitation tool call", error48);
|
|
25960
|
+
}
|
|
25487
25961
|
}
|
|
25488
25962
|
return result;
|
|
25489
25963
|
} catch (error48) {
|
|
@@ -25610,6 +26084,7 @@ var CodexElicitationHandler = class {
|
|
|
25610
26084
|
}
|
|
25611
26085
|
}
|
|
25612
26086
|
buildUserInputRequest(params) {
|
|
26087
|
+
const answerNotes = clientSupportsElicitationAnswerNotes(this.clientCapabilities);
|
|
25613
26088
|
const properties = {};
|
|
25614
26089
|
const required2 = [];
|
|
25615
26090
|
const questionIds = new Set(params.questions.map((question) => question.id));
|
|
@@ -25617,33 +26092,36 @@ var CodexElicitationHandler = class {
|
|
|
25617
26092
|
const options = question.options ?? [];
|
|
25618
26093
|
const hasOptions = options.length > 0;
|
|
25619
26094
|
const hasOtherAnswer = question.isOther && hasOptions;
|
|
25620
|
-
|
|
26095
|
+
if (!hasOtherAnswer || answerNotes) required2.push(question.id);
|
|
26096
|
+
properties[question.id] = {
|
|
26097
|
+
// Core v1 consumers use title as the short header and description
|
|
26098
|
+
// as the question. Keep that presentation contract at the boundary.
|
|
25621
26099
|
title: question.header || question.id,
|
|
25622
26100
|
description: question.question,
|
|
25623
|
-
_meta: lodyElicitationMeta({ secret: question.isSecret })
|
|
25624
|
-
};
|
|
25625
|
-
if (!hasOtherAnswer) {
|
|
25626
|
-
required2.push(question.id);
|
|
25627
|
-
}
|
|
25628
|
-
properties[question.id] = hasOptions ? {
|
|
25629
|
-
...base,
|
|
26101
|
+
_meta: lodyElicitationMeta({ secret: question.isSecret }),
|
|
25630
26102
|
type: "string",
|
|
25631
|
-
|
|
25632
|
-
|
|
25633
|
-
|
|
25634
|
-
|
|
25635
|
-
|
|
25636
|
-
|
|
25637
|
-
|
|
25638
|
-
|
|
26103
|
+
...hasOptions ? {
|
|
26104
|
+
oneOf: [
|
|
26105
|
+
...options.map((option) => ({
|
|
26106
|
+
const: option.label,
|
|
26107
|
+
title: option.label,
|
|
26108
|
+
...option.description ? { description: option.description } : {}
|
|
26109
|
+
})),
|
|
26110
|
+
...answerNotes && hasOtherAnswer && !options.some((option) => option.label === USER_INPUT_OTHER_OPTION) ? [{
|
|
26111
|
+
const: USER_INPUT_OTHER_OPTION,
|
|
26112
|
+
title: USER_INPUT_OTHER_OPTION,
|
|
26113
|
+
description: "Provide a different answer in the note field."
|
|
26114
|
+
}] : []
|
|
26115
|
+
]
|
|
26116
|
+
} : {}
|
|
25639
26117
|
};
|
|
25640
26118
|
if (hasOtherAnswer) {
|
|
25641
|
-
properties[
|
|
26119
|
+
properties[userInputNoteFieldId(question.id, questionIds)] = {
|
|
25642
26120
|
type: "string",
|
|
25643
|
-
title: "Other",
|
|
25644
|
-
description: "Type your own answer instead of choosing an option above.",
|
|
26121
|
+
title: answerNotes ? "Additional answer or note" : "Other",
|
|
26122
|
+
description: answerNotes ? "Optionally add context to your selected answer." : "Type your own answer instead of choosing an option above.",
|
|
25645
26123
|
_meta: lodyElicitationMeta({
|
|
25646
|
-
customAnswerFor: question.id,
|
|
26124
|
+
...answerNotes ? { noteFor: question.id } : { customAnswerFor: question.id },
|
|
25647
26125
|
secret: question.isSecret
|
|
25648
26126
|
})
|
|
25649
26127
|
};
|
|
@@ -25700,15 +26178,32 @@ var CodexElicitationHandler = class {
|
|
|
25700
26178
|
return { answers: {} };
|
|
25701
26179
|
}
|
|
25702
26180
|
const answers = {};
|
|
26181
|
+
const answerNotes = clientSupportsElicitationAnswerNotes(this.clientCapabilities);
|
|
25703
26182
|
const content = contentRecord(response.content);
|
|
25704
26183
|
const questionIds = new Set(params.questions.map((question) => question.id));
|
|
25705
26184
|
for (const question of params.questions) {
|
|
25706
|
-
const
|
|
25707
|
-
|
|
26185
|
+
const answerValues = [];
|
|
26186
|
+
const value = userInputResponseValue(content, question.id);
|
|
26187
|
+
if (value !== void 0) {
|
|
26188
|
+
answerValues.push(...Array.isArray(value) ? value.map(String) : [String(value)]);
|
|
26189
|
+
}
|
|
26190
|
+
if (question.isOther && question.options != null && question.options.length > 0) {
|
|
26191
|
+
const note = userInputResponseValue(content, userInputNoteFieldId(question.id, questionIds));
|
|
26192
|
+
if (answerNotes) {
|
|
26193
|
+
if (answerValues.length > 0 && typeof note === "string") {
|
|
26194
|
+
answerValues.push(`${USER_INPUT_NOTE_PREFIX}${note.trim()}`);
|
|
26195
|
+
}
|
|
26196
|
+
} else if (note !== void 0) {
|
|
26197
|
+
const notes = Array.isArray(note) ? note : [note];
|
|
26198
|
+
answerValues.splice(0, answerValues.length, USER_INPUT_OTHER_OPTION);
|
|
26199
|
+
answerValues.push(...notes.map((item) => `${USER_INPUT_NOTE_PREFIX}${String(item).trim()}`));
|
|
26200
|
+
}
|
|
26201
|
+
}
|
|
26202
|
+
if (answerValues.length === 0) {
|
|
25708
26203
|
continue;
|
|
25709
26204
|
}
|
|
25710
26205
|
answers[question.id] = {
|
|
25711
|
-
answers:
|
|
26206
|
+
answers: answerValues
|
|
25712
26207
|
};
|
|
25713
26208
|
}
|
|
25714
26209
|
return { answers };
|
|
@@ -25793,6 +26288,8 @@ function getCodexAuthMethods(clientCapabilities, env = process.env) {
|
|
|
25793
26288
|
function isCodexAuthRequest(request) {
|
|
25794
26289
|
return request.methodId === "api-key" || request.methodId === "chat-gpt" || request.methodId === "chat-gpt-device-code" || request.methodId === "gateway";
|
|
25795
26290
|
}
|
|
26291
|
+
var import_node2 = __toESM(require_main());
|
|
26292
|
+
var MAX_PROJECT_IDENTITY_GENERATION = 32;
|
|
25796
26293
|
function readWorktreeProject(meta3) {
|
|
25797
26294
|
if (typeof meta3 !== "object" || meta3 === null) return void 0;
|
|
25798
26295
|
const lody = meta3["lody"];
|
|
@@ -25816,55 +26313,40 @@ var WorktreeProjects = class {
|
|
|
25816
26313
|
if (!project) return void 0;
|
|
25817
26314
|
const originProjectPath = await realpath(project.originProjectPath);
|
|
25818
26315
|
const key = projectRootKey(originProjectPath);
|
|
25819
|
-
|
|
26316
|
+
const baseIdempotencyKey = `acp-project-v1:${createHash("sha256").update(key).digest("hex")}`;
|
|
26317
|
+
for (let generation = 0; generation <= MAX_PROJECT_IDENTITY_GENERATION; generation++) {
|
|
26318
|
+
const idempotencyKey = generation === 0 ? baseIdempotencyKey : `${baseIdempotencyKey}:g${generation}`;
|
|
26319
|
+
try {
|
|
26320
|
+
const response = await this.client.projectCreate({
|
|
26321
|
+
idempotencyKey,
|
|
26322
|
+
name: path__default.basename(originProjectPath) || originProjectPath,
|
|
26323
|
+
roots: [{ path: originProjectPath }]
|
|
26324
|
+
});
|
|
26325
|
+
return response.project.id;
|
|
26326
|
+
} catch (error48) {
|
|
26327
|
+
if (!isDeletedIdempotencyProject(error48, idempotencyKey)) throw error48;
|
|
26328
|
+
}
|
|
26329
|
+
}
|
|
26330
|
+
throw RequestError.internalError(
|
|
26331
|
+
{ originProjectPath, maxGeneration: MAX_PROJECT_IDENTITY_GENERATION },
|
|
26332
|
+
`Codex project recovery for ${originProjectPath} exhausted generations 0 through ${MAX_PROJECT_IDENTITY_GENERATION}`
|
|
26333
|
+
);
|
|
25820
26334
|
}
|
|
25821
|
-
async
|
|
25822
|
-
if (!project ||
|
|
26335
|
+
async backfill(thread, project) {
|
|
26336
|
+
if (!project || thread.projectId) return;
|
|
25823
26337
|
const projectId = await this.resolve(project);
|
|
25824
|
-
if (projectId
|
|
26338
|
+
if (projectId) {
|
|
25825
26339
|
await this.client.threadProjectUpdate({ threadId: thread.id, projectId });
|
|
25826
26340
|
}
|
|
25827
26341
|
}
|
|
25828
|
-
async findOrCreate(originProjectPath, key) {
|
|
25829
|
-
let cursor;
|
|
25830
|
-
const matches = /* @__PURE__ */ new Set();
|
|
25831
|
-
do {
|
|
25832
|
-
const page = await this.client.projectList({ limit: 100, ...cursor ? { cursor } : {} });
|
|
25833
|
-
for (const project of page.data) {
|
|
25834
|
-
for (const root of project.roots) {
|
|
25835
|
-
if (projectRootKey(root.path) === key || await this.matchesRoot(root.path, key)) {
|
|
25836
|
-
matches.add(project.id);
|
|
25837
|
-
break;
|
|
25838
|
-
}
|
|
25839
|
-
}
|
|
25840
|
-
}
|
|
25841
|
-
cursor = page.nextCursor ?? void 0;
|
|
25842
|
-
} while (cursor);
|
|
25843
|
-
if (matches.size > 1) {
|
|
25844
|
-
throw RequestError.invalidParams(void 0, "Multiple Codex projects use this root; consolidate the project assignments first");
|
|
25845
|
-
}
|
|
25846
|
-
const match = matches.values().next().value;
|
|
25847
|
-
if (match) return match;
|
|
25848
|
-
const idempotencyKey = `acp-project-v1:${createHash("sha256").update(key).digest("hex")}`;
|
|
25849
|
-
const response = await this.client.projectCreate({
|
|
25850
|
-
idempotencyKey,
|
|
25851
|
-
name: path__default.basename(originProjectPath) || originProjectPath,
|
|
25852
|
-
roots: [{ path: originProjectPath }]
|
|
25853
|
-
});
|
|
25854
|
-
return response.project.id;
|
|
25855
|
-
}
|
|
25856
|
-
async matchesRoot(storedPath, key) {
|
|
25857
|
-
try {
|
|
25858
|
-
return projectRootKey(await realpath(storedPath)) === key;
|
|
25859
|
-
} catch {
|
|
25860
|
-
return false;
|
|
25861
|
-
}
|
|
25862
|
-
}
|
|
25863
26342
|
};
|
|
25864
26343
|
function projectRootKey(originProjectPath) {
|
|
25865
26344
|
const normalized = path__default.resolve(originProjectPath);
|
|
25866
26345
|
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
25867
26346
|
}
|
|
26347
|
+
function isDeletedIdempotencyProject(error48, idempotencyKey) {
|
|
26348
|
+
return error48 instanceof import_node2.ResponseError && error48.code === import_node2.ErrorCodes.InternalError && error48.message.includes(`idempotency key refers to deleted project: ${idempotencyKey}`);
|
|
26349
|
+
}
|
|
25868
26350
|
var isDockerCached;
|
|
25869
26351
|
function hasDockerEnv() {
|
|
25870
26352
|
try {
|
|
@@ -26632,7 +27114,7 @@ var package_default = {
|
|
|
26632
27114
|
publishConfig: {
|
|
26633
27115
|
access: "public"
|
|
26634
27116
|
},
|
|
26635
|
-
version: "1.
|
|
27117
|
+
version: "1.12.0",
|
|
26636
27118
|
description: "An ACP-compatible coding agent powered by Codex",
|
|
26637
27119
|
main: "dist/index.js",
|
|
26638
27120
|
bin: {
|
|
@@ -26702,7 +27184,7 @@ var package_default = {
|
|
|
26702
27184
|
dependencies: {
|
|
26703
27185
|
"@agentclientprotocol/sdk": "^1.4.0",
|
|
26704
27186
|
"@openai/codex": "^0.154.0",
|
|
26705
|
-
"acp-extension-core": "0.1.
|
|
27187
|
+
"acp-extension-core": "0.1.6",
|
|
26706
27188
|
diff: "^9.0.0",
|
|
26707
27189
|
open: "^11.0.1",
|
|
26708
27190
|
"vscode-jsonrpc": "^9.0.1",
|
|
@@ -26732,7 +27214,7 @@ function createCodexCollaborationMode(mode, currentModelId) {
|
|
|
26732
27214
|
}
|
|
26733
27215
|
function isAbsolutePathLike(value) {
|
|
26734
27216
|
const trimmed = value.trim();
|
|
26735
|
-
return path__default.isAbsolute(trimmed) ||
|
|
27217
|
+
return path__default.isAbsolute(trimmed) || isWindowsAbsolutePath2(trimmed);
|
|
26736
27218
|
}
|
|
26737
27219
|
function arePathsEqual(left, right) {
|
|
26738
27220
|
return normalizePathForComparison(left) === normalizePathForComparison(right);
|
|
@@ -26750,7 +27232,7 @@ function normalizePathForComparison(value) {
|
|
|
26750
27232
|
if (trimmed.length === 0) {
|
|
26751
27233
|
return "";
|
|
26752
27234
|
}
|
|
26753
|
-
if (
|
|
27235
|
+
if (isWindowsAbsolutePath2(trimmed)) {
|
|
26754
27236
|
const normalized2 = path__default.win32.normalize(trimmed).replace(/\\/g, "/");
|
|
26755
27237
|
return trimTrailingPathSeparators(normalized2).toLowerCase();
|
|
26756
27238
|
}
|
|
@@ -26758,12 +27240,12 @@ function normalizePathForComparison(value) {
|
|
|
26758
27240
|
const normalized = path__default.posix.normalize(pathForComparison);
|
|
26759
27241
|
return trimTrailingPathSeparators(normalized);
|
|
26760
27242
|
}
|
|
26761
|
-
function
|
|
27243
|
+
function isWindowsAbsolutePath2(value) {
|
|
26762
27244
|
const portableValue = value.replace(/\\/g, "/");
|
|
26763
27245
|
return /^[A-Za-z]:\//.test(portableValue) || /^\/\/[^/]+\/[^/]+/.test(portableValue);
|
|
26764
27246
|
}
|
|
26765
27247
|
function shouldComparePathCaseInsensitive(value) {
|
|
26766
|
-
return
|
|
27248
|
+
return isWindowsAbsolutePath2(value) || /^[A-Za-z]:/.test(value) || value.includes("\\");
|
|
26767
27249
|
}
|
|
26768
27250
|
function trimTrailingPathSeparators(value) {
|
|
26769
27251
|
let trimmed = value;
|
|
@@ -26775,296 +27257,6 @@ function trimTrailingPathSeparators(value) {
|
|
|
26775
27257
|
function isRootPath(value) {
|
|
26776
27258
|
return value === "/" || /^[A-Za-z]:\/$/.test(value) || /^\/\/[^/]+\/[^/]+\/$/.test(value);
|
|
26777
27259
|
}
|
|
26778
|
-
var AGENT_FILE_CHANGE_REPORT_VERSION = 1;
|
|
26779
|
-
var AGENT_FILE_CHANGE_REPORT_TIMEOUT_MS = 3e4;
|
|
26780
|
-
var AGENT_FILE_CHANGE_REPORT_MAX_PATHS = 1024;
|
|
26781
|
-
var AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH = 4096;
|
|
26782
|
-
var AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES = 256 * 1024;
|
|
26783
|
-
var AGENT_FILE_CHANGE_REPORT_MAX_UNCERTAINTY_LENGTH = 2e3;
|
|
26784
|
-
var AGENT_FILE_CHANGE_REPORT_OUTPUT_SCHEMA = {
|
|
26785
|
-
type: "object",
|
|
26786
|
-
additionalProperties: false,
|
|
26787
|
-
required: ["paths", "complete", "uncertainty"],
|
|
26788
|
-
properties: {
|
|
26789
|
-
paths: {
|
|
26790
|
-
type: "array",
|
|
26791
|
-
items: { type: "string" }
|
|
26792
|
-
},
|
|
26793
|
-
complete: { type: "boolean" },
|
|
26794
|
-
uncertainty: {
|
|
26795
|
-
anyOf: [{
|
|
26796
|
-
type: "string",
|
|
26797
|
-
maxLength: AGENT_FILE_CHANGE_REPORT_MAX_UNCERTAINTY_LENGTH
|
|
26798
|
-
}, {
|
|
26799
|
-
type: "null"
|
|
26800
|
-
}]
|
|
26801
|
-
}
|
|
26802
|
-
}
|
|
26803
|
-
};
|
|
26804
|
-
var AGENT_FILE_CHANGE_REPORT_DEVELOPER_INSTRUCTIONS = `You are running an internal, read-only file-change audit for the immediately preceding turn.
|
|
26805
|
-
Do not modify files, run commands that can modify files, or ask the user questions.
|
|
26806
|
-
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.
|
|
26807
|
-
Do not report files that were only read or inspected.
|
|
26808
|
-
You may use read-only inspection when needed. If the list may be incomplete, set complete to false and briefly explain why in uncertainty.`;
|
|
26809
|
-
function createAgentFileChangeReportPrompt(workspace) {
|
|
26810
|
-
return `List the paths changed by the immediately preceding turn.
|
|
26811
|
-
Return only the structured result required by the output schema.
|
|
26812
|
-
Relative paths are resolved against the working directory.
|
|
26813
|
-
Working directory: ${JSON.stringify(workspace.cwd)}
|
|
26814
|
-
Additional allowed directories: ${JSON.stringify(workspace.additionalDirectories)}`;
|
|
26815
|
-
}
|
|
26816
|
-
function parseAgentFileChangeReportRequest(meta3) {
|
|
26817
|
-
const jetbrains = asRecord(meta3?.[JETBRAINS_META_KEY]);
|
|
26818
|
-
const air = asRecord(jetbrains?.[AIR_META_KEY]);
|
|
26819
|
-
const request = asRecord(air?.[AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY]);
|
|
26820
|
-
if (request === null || !hasOnlyKeys(request, ["version", "requestId"]) || request["version"] !== AGENT_FILE_CHANGE_REPORT_VERSION) {
|
|
26821
|
-
return null;
|
|
26822
|
-
}
|
|
26823
|
-
const requestId = request["requestId"];
|
|
26824
|
-
if (typeof requestId !== "string" || !/^[A-Za-z0-9._:-]{1,128}$/.test(requestId)) {
|
|
26825
|
-
return null;
|
|
26826
|
-
}
|
|
26827
|
-
return { version: AGENT_FILE_CHANGE_REPORT_VERSION, requestId };
|
|
26828
|
-
}
|
|
26829
|
-
function createReportedAgentFileChangeReport(requestId, turn, workspace) {
|
|
26830
|
-
const modelReport = parseModelFileChangeReport(turn);
|
|
26831
|
-
const normalized = normalizeModelFileChangeReport(modelReport, workspace);
|
|
26832
|
-
return fitReportedAgentFileChangeReport({
|
|
26833
|
-
version: AGENT_FILE_CHANGE_REPORT_VERSION,
|
|
26834
|
-
requestId,
|
|
26835
|
-
status: "reported",
|
|
26836
|
-
...normalized
|
|
26837
|
-
});
|
|
26838
|
-
}
|
|
26839
|
-
function createUnavailableAgentFileChangeReport(requestId, reason) {
|
|
26840
|
-
return {
|
|
26841
|
-
version: AGENT_FILE_CHANGE_REPORT_VERSION,
|
|
26842
|
-
requestId,
|
|
26843
|
-
status: "unavailable",
|
|
26844
|
-
reason
|
|
26845
|
-
};
|
|
26846
|
-
}
|
|
26847
|
-
var AgentFileChangeReportError = class extends Error {
|
|
26848
|
-
reason;
|
|
26849
|
-
constructor(reason, message) {
|
|
26850
|
-
super(message);
|
|
26851
|
-
this.name = "AgentFileChangeReportError";
|
|
26852
|
-
this.reason = reason;
|
|
26853
|
-
}
|
|
26854
|
-
};
|
|
26855
|
-
function parseModelFileChangeReport(turn) {
|
|
26856
|
-
switch (turn.status) {
|
|
26857
|
-
case "interrupted":
|
|
26858
|
-
throw new AgentFileChangeReportError("cancelled", "The audit turn was interrupted");
|
|
26859
|
-
case "failed":
|
|
26860
|
-
throw new AgentFileChangeReportError(
|
|
26861
|
-
"providerError",
|
|
26862
|
-
`The audit turn failed${turn.error?.message ? `: ${turn.error.message}` : ""}`
|
|
26863
|
-
);
|
|
26864
|
-
case "inProgress":
|
|
26865
|
-
throw new AgentFileChangeReportError("notReported", "The audit turn did not complete");
|
|
26866
|
-
}
|
|
26867
|
-
let text = null;
|
|
26868
|
-
for (let index = turn.items.length - 1; index >= 0; index -= 1) {
|
|
26869
|
-
const item = turn.items[index];
|
|
26870
|
-
if (item?.type === "agentMessage") {
|
|
26871
|
-
text = item.text;
|
|
26872
|
-
break;
|
|
26873
|
-
}
|
|
26874
|
-
}
|
|
26875
|
-
if (text === null) {
|
|
26876
|
-
throw new AgentFileChangeReportError("notReported", "The audit turn returned no agent message");
|
|
26877
|
-
}
|
|
26878
|
-
let value;
|
|
26879
|
-
try {
|
|
26880
|
-
value = JSON.parse(text);
|
|
26881
|
-
} catch {
|
|
26882
|
-
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned invalid JSON");
|
|
26883
|
-
}
|
|
26884
|
-
const report = asRecord(value);
|
|
26885
|
-
if (report === null || !hasOnlyKeys(report, ["paths", "complete", "uncertainty"])) {
|
|
26886
|
-
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned an invalid object");
|
|
26887
|
-
}
|
|
26888
|
-
const paths = report["paths"];
|
|
26889
|
-
const complete = report["complete"];
|
|
26890
|
-
const uncertainty = report["uncertainty"];
|
|
26891
|
-
if (!Array.isArray(paths) || !paths.every((item) => typeof item === "string") || typeof complete !== "boolean" || uncertainty !== void 0 && uncertainty !== null && typeof uncertainty !== "string") {
|
|
26892
|
-
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned invalid fields");
|
|
26893
|
-
}
|
|
26894
|
-
const normalizedUncertainty = typeof uncertainty === "string" ? uncertainty.trim() : void 0;
|
|
26895
|
-
if (normalizedUncertainty !== void 0 && normalizedUncertainty.length > AGENT_FILE_CHANGE_REPORT_MAX_UNCERTAINTY_LENGTH) {
|
|
26896
|
-
throw new AgentFileChangeReportError("invalidOutput", "The audit turn returned oversized uncertainty");
|
|
26897
|
-
}
|
|
26898
|
-
return {
|
|
26899
|
-
paths,
|
|
26900
|
-
complete,
|
|
26901
|
-
...normalizedUncertainty ? { uncertainty: normalizedUncertainty } : {}
|
|
26902
|
-
};
|
|
26903
|
-
}
|
|
26904
|
-
function fitReportedAgentFileChangeReport(report) {
|
|
26905
|
-
const paths = [...report.paths];
|
|
26906
|
-
let truncated = report.truncated;
|
|
26907
|
-
let fitted = report;
|
|
26908
|
-
while (Buffer.byteLength(JSON.stringify(fitted), "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
|
|
26909
|
-
if (paths.length === 0) {
|
|
26910
|
-
throw new AgentFileChangeReportError("invalidOutput", "The audit report exceeds the wire limit");
|
|
26911
|
-
}
|
|
26912
|
-
paths.pop();
|
|
26913
|
-
truncated = true;
|
|
26914
|
-
fitted = {
|
|
26915
|
-
...report,
|
|
26916
|
-
paths: [...paths],
|
|
26917
|
-
declaredComplete: false,
|
|
26918
|
-
truncated
|
|
26919
|
-
};
|
|
26920
|
-
}
|
|
26921
|
-
return fitted;
|
|
26922
|
-
}
|
|
26923
|
-
function normalizeModelFileChangeReport(report, workspace) {
|
|
26924
|
-
const cwd = normalizeWorkspaceRoot(workspace.cwd);
|
|
26925
|
-
if (cwd === null) {
|
|
26926
|
-
throw new AgentFileChangeReportError("providerError", "The session working directory is not absolute");
|
|
26927
|
-
}
|
|
26928
|
-
const roots = [cwd, ...workspace.additionalDirectories.flatMap((directory) => {
|
|
26929
|
-
const root = normalizeWorkspaceRoot(directory);
|
|
26930
|
-
return root === null || root.flavor !== cwd.flavor ? [] : [root];
|
|
26931
|
-
})];
|
|
26932
|
-
const paths = [];
|
|
26933
|
-
const seen = /* @__PURE__ */ new Set();
|
|
26934
|
-
let totalBytes = 0;
|
|
26935
|
-
let truncated = false;
|
|
26936
|
-
for (const reportedPath of report.paths) {
|
|
26937
|
-
if (reportedPath.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
|
|
26938
|
-
truncated = true;
|
|
26939
|
-
continue;
|
|
26940
|
-
}
|
|
26941
|
-
const normalized = normalizeReportedPath(reportedPath, cwd, roots);
|
|
26942
|
-
if (normalized === null || normalized.value.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
|
|
26943
|
-
truncated = true;
|
|
26944
|
-
continue;
|
|
26945
|
-
}
|
|
26946
|
-
const key = normalized.flavor === "windows" ? normalized.value.toLowerCase() : normalized.value;
|
|
26947
|
-
if (seen.has(key)) {
|
|
26948
|
-
continue;
|
|
26949
|
-
}
|
|
26950
|
-
const bytes = Buffer.byteLength(normalized.value, "utf8");
|
|
26951
|
-
if (paths.length >= AGENT_FILE_CHANGE_REPORT_MAX_PATHS || totalBytes + bytes > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
|
|
26952
|
-
truncated = true;
|
|
26953
|
-
continue;
|
|
26954
|
-
}
|
|
26955
|
-
seen.add(key);
|
|
26956
|
-
paths.push(normalized.value);
|
|
26957
|
-
totalBytes += bytes;
|
|
26958
|
-
}
|
|
26959
|
-
return {
|
|
26960
|
-
paths,
|
|
26961
|
-
declaredComplete: report.complete && !truncated,
|
|
26962
|
-
truncated,
|
|
26963
|
-
...report.uncertainty ? { uncertainty: report.uncertainty } : {}
|
|
26964
|
-
};
|
|
26965
|
-
}
|
|
26966
|
-
function normalizeWorkspaceRoot(value) {
|
|
26967
|
-
const trimmed = value.trim();
|
|
26968
|
-
if (!isValidPathText(trimmed)) {
|
|
26969
|
-
return null;
|
|
26970
|
-
}
|
|
26971
|
-
if (isWindowsAbsolutePath2(trimmed)) {
|
|
26972
|
-
return canonicalizeWorkspaceRoot({
|
|
26973
|
-
value: path__default.win32.normalize(trimmed.replace(/\//g, "\\")),
|
|
26974
|
-
flavor: "windows"
|
|
26975
|
-
});
|
|
26976
|
-
}
|
|
26977
|
-
if (path__default.posix.isAbsolute(trimmed)) {
|
|
26978
|
-
return canonicalizeWorkspaceRoot({
|
|
26979
|
-
value: path__default.posix.normalize(trimmed.replace(/\\/g, "/")),
|
|
26980
|
-
flavor: "posix"
|
|
26981
|
-
});
|
|
26982
|
-
}
|
|
26983
|
-
return null;
|
|
26984
|
-
}
|
|
26985
|
-
function normalizeReportedPath(value, cwd, roots) {
|
|
26986
|
-
const trimmed = value.trim();
|
|
26987
|
-
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)) {
|
|
26988
|
-
return null;
|
|
26989
|
-
}
|
|
26990
|
-
let candidate;
|
|
26991
|
-
if (isWindowsAbsolutePath2(trimmed)) {
|
|
26992
|
-
candidate = { value: path__default.win32.normalize(trimmed.replace(/\//g, "\\")), flavor: "windows" };
|
|
26993
|
-
} else if (path__default.posix.isAbsolute(trimmed)) {
|
|
26994
|
-
candidate = { value: path__default.posix.normalize(trimmed.replace(/\\/g, "/")), flavor: "posix" };
|
|
26995
|
-
} else if (cwd.flavor === "windows") {
|
|
26996
|
-
candidate = {
|
|
26997
|
-
value: path__default.win32.resolve(cwd.value, trimmed.replace(/\//g, "\\")),
|
|
26998
|
-
flavor: "windows"
|
|
26999
|
-
};
|
|
27000
|
-
} else {
|
|
27001
|
-
candidate = {
|
|
27002
|
-
value: path__default.posix.resolve(cwd.value, trimmed.replace(/\\/g, "/")),
|
|
27003
|
-
flavor: "posix"
|
|
27004
|
-
};
|
|
27005
|
-
}
|
|
27006
|
-
candidate = canonicalizeReportedPath(candidate);
|
|
27007
|
-
return roots.some((root) => pathIsStrictlyInside(root, candidate)) ? candidate : null;
|
|
27008
|
-
}
|
|
27009
|
-
function canonicalizeWorkspaceRoot(root) {
|
|
27010
|
-
if (!isNativePathFlavor(root.flavor)) {
|
|
27011
|
-
return root;
|
|
27012
|
-
}
|
|
27013
|
-
return { ...root, value: canonicalizeFromExistingAncestor(root.value) };
|
|
27014
|
-
}
|
|
27015
|
-
function canonicalizeReportedPath(candidate) {
|
|
27016
|
-
if (!isNativePathFlavor(candidate.flavor)) {
|
|
27017
|
-
return candidate;
|
|
27018
|
-
}
|
|
27019
|
-
const parent = canonicalizeFromExistingAncestor(path__default.dirname(candidate.value));
|
|
27020
|
-
return { ...candidate, value: path__default.resolve(parent, path__default.basename(candidate.value)) };
|
|
27021
|
-
}
|
|
27022
|
-
function canonicalizeFromExistingAncestor(value) {
|
|
27023
|
-
const original = path__default.resolve(value);
|
|
27024
|
-
let current = original;
|
|
27025
|
-
const missingSegments = [];
|
|
27026
|
-
while (true) {
|
|
27027
|
-
try {
|
|
27028
|
-
const canonical = fs__default.realpathSync.native(current);
|
|
27029
|
-
return path__default.resolve(canonical, ...missingSegments.reverse());
|
|
27030
|
-
} catch (error48) {
|
|
27031
|
-
if (!isMissingPathError(error48)) return original;
|
|
27032
|
-
}
|
|
27033
|
-
const parent = path__default.dirname(current);
|
|
27034
|
-
if (parent === current) return original;
|
|
27035
|
-
missingSegments.push(path__default.basename(current));
|
|
27036
|
-
current = parent;
|
|
27037
|
-
}
|
|
27038
|
-
}
|
|
27039
|
-
function isMissingPathError(error48) {
|
|
27040
|
-
if (typeof error48 !== "object" || error48 === null || !("code" in error48)) return false;
|
|
27041
|
-
return error48.code === "ENOENT" || error48.code === "ENOTDIR";
|
|
27042
|
-
}
|
|
27043
|
-
function isNativePathFlavor(flavor) {
|
|
27044
|
-
return process.platform === "win32" ? flavor === "windows" : flavor === "posix";
|
|
27045
|
-
}
|
|
27046
|
-
function pathIsStrictlyInside(root, candidate) {
|
|
27047
|
-
if (root.flavor !== candidate.flavor) {
|
|
27048
|
-
return false;
|
|
27049
|
-
}
|
|
27050
|
-
const pathImplementation = root.flavor === "windows" ? path__default.win32 : path__default.posix;
|
|
27051
|
-
const relative = pathImplementation.relative(root.value, candidate.value);
|
|
27052
|
-
return relative.length > 0 && !pathImplementation.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${pathImplementation.sep}`);
|
|
27053
|
-
}
|
|
27054
|
-
function isWindowsAbsolutePath2(value) {
|
|
27055
|
-
const portable = value.replace(/\\/g, "/");
|
|
27056
|
-
return /^[A-Za-z]:\//.test(portable) || /^\/\/[^/]+\/[^/]+(?:\/|$)/.test(portable);
|
|
27057
|
-
}
|
|
27058
|
-
function isValidPathText(value) {
|
|
27059
|
-
return value.length > 0 && !/[\u0000-\u001F\u007F-\u009F]/.test(value);
|
|
27060
|
-
}
|
|
27061
|
-
function asRecord(value) {
|
|
27062
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
27063
|
-
}
|
|
27064
|
-
function hasOnlyKeys(value, allowed) {
|
|
27065
|
-
const allowedKeys = new Set(allowed);
|
|
27066
|
-
return Object.keys(value).every((key) => allowedKeys.has(key));
|
|
27067
|
-
}
|
|
27068
27260
|
var CodexSubagentSubscriptions = class {
|
|
27069
27261
|
constructor(client) {
|
|
27070
27262
|
this.client = client;
|
|
@@ -27182,6 +27374,7 @@ async function forkSession(request, additionalDirectories, dependencies) {
|
|
|
27182
27374
|
await dependencies.refreshSkills(request.cwd, additionalDirectories);
|
|
27183
27375
|
const lastTurnId = await resolveForkTurnId(request, dependencies.codexClient);
|
|
27184
27376
|
const response = await dependencies.codexClient.threadFork({
|
|
27377
|
+
excludeTurns: true,
|
|
27185
27378
|
config: await dependencies.createSessionConfig(
|
|
27186
27379
|
request.cwd,
|
|
27187
27380
|
additionalDirectories,
|
|
@@ -27193,7 +27386,7 @@ async function forkSession(request, additionalDirectories, dependencies) {
|
|
|
27193
27386
|
threadId: request.sessionId
|
|
27194
27387
|
});
|
|
27195
27388
|
try {
|
|
27196
|
-
await dependencies.
|
|
27389
|
+
await dependencies.backfillProject(response.thread, project);
|
|
27197
27390
|
} catch (error48) {
|
|
27198
27391
|
await dependencies.codexClient.threadUnsubscribe({ threadId: response.thread.id });
|
|
27199
27392
|
throw error48;
|
|
@@ -27214,10 +27407,7 @@ async function resolveForkTurnId(request, codexClient) {
|
|
|
27214
27407
|
if (lodyTurnId !== null) return lodyTurnId;
|
|
27215
27408
|
const forkPoint = readAirForkPoint(request._meta);
|
|
27216
27409
|
if (!forkPoint) return void 0;
|
|
27217
|
-
const history = await codexClient.
|
|
27218
|
-
threadId: request.sessionId,
|
|
27219
|
-
includeTurns: true
|
|
27220
|
-
});
|
|
27410
|
+
const history = await codexClient.threadReadWithHistory(request.sessionId);
|
|
27221
27411
|
const candidateIds = airForkMessageIdCandidates(forkPoint.messageId);
|
|
27222
27412
|
const itemTurnId = candidateIds.map((candidateId) => history.thread.turns.find((turn) => turn.items.some((item) => item.id === candidateId))?.id).find((turnId) => turnId !== void 0);
|
|
27223
27413
|
if (itemTurnId) return itemTurnId;
|
|
@@ -27611,11 +27801,7 @@ var CodexAcpClient = class {
|
|
|
27611
27801
|
return this.codexClient.accountRateLimitsRead();
|
|
27612
27802
|
}
|
|
27613
27803
|
async readSessionHistory(sessionId) {
|
|
27614
|
-
|
|
27615
|
-
threadId: sessionId,
|
|
27616
|
-
includeTurns: true
|
|
27617
|
-
});
|
|
27618
|
-
return response.thread;
|
|
27804
|
+
return (await this.codexClient.threadReadWithHistory(sessionId)).thread;
|
|
27619
27805
|
}
|
|
27620
27806
|
/**
|
|
27621
27807
|
* Presentable name of the gateway the agent itself authenticated against
|
|
@@ -27649,13 +27835,14 @@ var CodexAcpClient = class {
|
|
|
27649
27835
|
const additionalDirectories = readAdditionalDirectories(request.cwd, request.additionalDirectories, request._meta);
|
|
27650
27836
|
await this.refreshSkills(request.cwd, additionalDirectories);
|
|
27651
27837
|
const response = await this.codexClient.threadResume({
|
|
27838
|
+
excludeTurns: true,
|
|
27652
27839
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
|
|
27653
27840
|
cwd: request.cwd,
|
|
27654
27841
|
modelProvider: await this.getResumeModelProvider(),
|
|
27655
27842
|
threadId: request.sessionId
|
|
27656
27843
|
});
|
|
27657
27844
|
onSubscribed?.(request.sessionId);
|
|
27658
|
-
await this.worktreeProjects.
|
|
27845
|
+
await this.worktreeProjects.backfill(response.thread, project);
|
|
27659
27846
|
const codexModels = await this.fetchAvailableModels();
|
|
27660
27847
|
const currentModelId = this.createModelId(codexModels, response.model, response.reasoningEffort).toString();
|
|
27661
27848
|
return {
|
|
@@ -27672,7 +27859,7 @@ var CodexAcpClient = class {
|
|
|
27672
27859
|
const additionalDirectories = readAdditionalDirectories(request.cwd, request.additionalDirectories, request._meta);
|
|
27673
27860
|
return await forkSession(request, additionalDirectories, {
|
|
27674
27861
|
codexClient: this.codexClient,
|
|
27675
|
-
|
|
27862
|
+
backfillProject: (thread, project) => this.worktreeProjects.backfill(thread, project),
|
|
27676
27863
|
refreshSkills: (cwd, directories) => this.refreshSkills(cwd, directories),
|
|
27677
27864
|
createSessionConfig: (cwd, directories, mcpServers) => this.createSessionConfig(cwd, directories, mcpServers),
|
|
27678
27865
|
getResumeModelProvider: () => this.getResumeModelProvider(),
|
|
@@ -27686,17 +27873,18 @@ var CodexAcpClient = class {
|
|
|
27686
27873
|
const additionalDirectories = readAdditionalDirectories(request.cwd, request.additionalDirectories, request._meta);
|
|
27687
27874
|
await this.refreshSkills(request.cwd, additionalDirectories);
|
|
27688
27875
|
const response = await this.codexClient.threadResume({
|
|
27876
|
+
excludeTurns: true,
|
|
27689
27877
|
config: await this.createSessionConfig(request.cwd, additionalDirectories, request.mcpServers ?? []),
|
|
27690
27878
|
cwd: request.cwd,
|
|
27691
27879
|
modelProvider: await this.getResumeModelProvider(),
|
|
27692
27880
|
threadId: request.sessionId
|
|
27693
27881
|
});
|
|
27694
27882
|
onSubscribed?.();
|
|
27695
|
-
await this.worktreeProjects.
|
|
27696
|
-
const
|
|
27697
|
-
|
|
27698
|
-
|
|
27699
|
-
});
|
|
27883
|
+
await this.worktreeProjects.backfill(response.thread, project);
|
|
27884
|
+
const thread = response.thread.historyMode === "paginated" ? {
|
|
27885
|
+
...response.thread,
|
|
27886
|
+
turns: response.turnsBackwardsCursor === null ? [] : await this.codexClient.threadReadHistory(response.thread.id, response.turnsBackwardsCursor)
|
|
27887
|
+
} : (await this.codexClient.threadReadWithHistory(response.thread.id)).thread;
|
|
27700
27888
|
const codexModels = await this.fetchAvailableModels();
|
|
27701
27889
|
const currentModelId = this.createModelId(codexModels, response.model, response.reasoningEffort).toString();
|
|
27702
27890
|
return {
|
|
@@ -27706,7 +27894,7 @@ var CodexAcpClient = class {
|
|
|
27706
27894
|
collaborationMode: this.getCollaborationMode(response.thread.id),
|
|
27707
27895
|
modelProvider: response.modelProvider,
|
|
27708
27896
|
currentServiceTier: response.serviceTier ?? null,
|
|
27709
|
-
thread
|
|
27897
|
+
thread,
|
|
27710
27898
|
additionalDirectories
|
|
27711
27899
|
};
|
|
27712
27900
|
}
|
|
@@ -27825,7 +28013,7 @@ var CodexAcpClient = class {
|
|
|
27825
28013
|
baseUrl: activeProvider.baseUrl
|
|
27826
28014
|
});
|
|
27827
28015
|
const mergedConfig = {
|
|
27828
|
-
...mergeGatewayConfig(this.config, this.gatewayConfig),
|
|
28016
|
+
...forceGitRootTurnDiffPaths(mergeGatewayConfig(this.config, this.gatewayConfig)),
|
|
27829
28017
|
projects: Object.fromEntries(sessionRoots.map((root) => [root, {
|
|
27830
28018
|
trust_level: "trusted"
|
|
27831
28019
|
}]))
|
|
@@ -27994,100 +28182,6 @@ var CodexAcpClient = class {
|
|
|
27994
28182
|
};
|
|
27995
28183
|
return await this.codexClient.runTurn(params, onTurnStarted);
|
|
27996
28184
|
}
|
|
27997
|
-
async runAgentFileChangeReport(params) {
|
|
27998
|
-
if (params.signal?.aborted) {
|
|
27999
|
-
return createUnavailableAgentFileChangeReport(params.requestId, "cancelled");
|
|
28000
|
-
}
|
|
28001
|
-
const budget = new AgentFileChangeReportBudget(params.signal);
|
|
28002
|
-
let forkThreadId = null;
|
|
28003
|
-
let auditTurnId = null;
|
|
28004
|
-
let auditTurnCompleted = false;
|
|
28005
|
-
let lateStopReason = null;
|
|
28006
|
-
try {
|
|
28007
|
-
const forkPromise = this.codexClient.threadFork({
|
|
28008
|
-
threadId: params.sessionId,
|
|
28009
|
-
lastTurnId: params.turnId,
|
|
28010
|
-
cwd: params.workspace.cwd,
|
|
28011
|
-
approvalPolicy: "never",
|
|
28012
|
-
sandbox: "read-only",
|
|
28013
|
-
developerInstructions: AGENT_FILE_CHANGE_REPORT_DEVELOPER_INSTRUCTIONS,
|
|
28014
|
-
ephemeral: true
|
|
28015
|
-
});
|
|
28016
|
-
void forkPromise.then((fork2) => {
|
|
28017
|
-
if (lateStopReason !== null && forkThreadId === null) {
|
|
28018
|
-
void this.unsubscribeAgentFileChangeReportThread(fork2.thread.id, budget);
|
|
28019
|
-
}
|
|
28020
|
-
}, () => {
|
|
28021
|
-
});
|
|
28022
|
-
const fork = await budget.wait(forkPromise);
|
|
28023
|
-
forkThreadId = fork.thread.id;
|
|
28024
|
-
const turnPromise = this.codexClient.runTurn({
|
|
28025
|
-
threadId: forkThreadId,
|
|
28026
|
-
input: [{
|
|
28027
|
-
type: "text",
|
|
28028
|
-
text: createAgentFileChangeReportPrompt(params.workspace),
|
|
28029
|
-
text_elements: []
|
|
28030
|
-
}],
|
|
28031
|
-
cwd: params.workspace.cwd,
|
|
28032
|
-
approvalPolicy: "never",
|
|
28033
|
-
sandboxPolicy: { type: "readOnly", networkAccess: false },
|
|
28034
|
-
summary: "none",
|
|
28035
|
-
outputSchema: AGENT_FILE_CHANGE_REPORT_OUTPUT_SCHEMA
|
|
28036
|
-
}, (turnId) => {
|
|
28037
|
-
auditTurnId = turnId;
|
|
28038
|
-
if (lateStopReason !== null && forkThreadId !== null) {
|
|
28039
|
-
void this.interruptAgentFileChangeReport(forkThreadId, turnId, lateStopReason, budget);
|
|
28040
|
-
}
|
|
28041
|
-
});
|
|
28042
|
-
const outcome = await budget.wait(turnPromise);
|
|
28043
|
-
auditTurnCompleted = true;
|
|
28044
|
-
return createReportedAgentFileChangeReport(
|
|
28045
|
-
params.requestId,
|
|
28046
|
-
outcome.turn,
|
|
28047
|
-
params.workspace
|
|
28048
|
-
);
|
|
28049
|
-
} catch (error48) {
|
|
28050
|
-
if (error48 instanceof AgentFileChangeReportBudgetError) {
|
|
28051
|
-
lateStopReason = error48.reason;
|
|
28052
|
-
if (!auditTurnCompleted && forkThreadId !== null && auditTurnId !== null) {
|
|
28053
|
-
await this.interruptAgentFileChangeReport(
|
|
28054
|
-
forkThreadId,
|
|
28055
|
-
auditTurnId,
|
|
28056
|
-
error48.reason,
|
|
28057
|
-
budget
|
|
28058
|
-
);
|
|
28059
|
-
}
|
|
28060
|
-
return createUnavailableAgentFileChangeReport(params.requestId, error48.reason);
|
|
28061
|
-
}
|
|
28062
|
-
if (error48 instanceof AgentFileChangeReportError) {
|
|
28063
|
-
logger.error("Agent file-change report unavailable", error48);
|
|
28064
|
-
return createUnavailableAgentFileChangeReport(params.requestId, error48.reason);
|
|
28065
|
-
}
|
|
28066
|
-
logger.error("Agent file-change report failed", error48);
|
|
28067
|
-
return createUnavailableAgentFileChangeReport(params.requestId, "providerError");
|
|
28068
|
-
} finally {
|
|
28069
|
-
if (forkThreadId !== null) {
|
|
28070
|
-
await this.unsubscribeAgentFileChangeReportThread(forkThreadId, budget);
|
|
28071
|
-
}
|
|
28072
|
-
}
|
|
28073
|
-
}
|
|
28074
|
-
async interruptAgentFileChangeReport(threadId, turnId, reason, budget) {
|
|
28075
|
-
this.codexClient.markTurnStale(threadId, turnId);
|
|
28076
|
-
try {
|
|
28077
|
-
await budget.wait(this.codexClient.turnInterrupt({ threadId, turnId }));
|
|
28078
|
-
} catch (error48) {
|
|
28079
|
-
logger.error(`Failed to interrupt ${reason} agent file-change report`, error48);
|
|
28080
|
-
} finally {
|
|
28081
|
-
this.codexClient.resolveTurnInterrupted(threadId, turnId);
|
|
28082
|
-
}
|
|
28083
|
-
}
|
|
28084
|
-
async unsubscribeAgentFileChangeReportThread(threadId, budget) {
|
|
28085
|
-
try {
|
|
28086
|
-
await budget.wait(this.codexClient.threadUnsubscribe({ threadId }));
|
|
28087
|
-
} catch (error48) {
|
|
28088
|
-
logger.error("Failed to unsubscribe the agent file-change report thread", error48);
|
|
28089
|
-
}
|
|
28090
|
-
}
|
|
28091
28185
|
async setCollaborationMode(sessionId, mode, currentModelId) {
|
|
28092
28186
|
await this.codexClient.threadSettingsUpdate({
|
|
28093
28187
|
threadId: sessionId,
|
|
@@ -28249,58 +28343,6 @@ var CodexAcpClient = class {
|
|
|
28249
28343
|
};
|
|
28250
28344
|
}
|
|
28251
28345
|
};
|
|
28252
|
-
var AgentFileChangeReportBudgetError = class extends Error {
|
|
28253
|
-
constructor(reason) {
|
|
28254
|
-
super(`Agent file-change report ${reason}`);
|
|
28255
|
-
this.reason = reason;
|
|
28256
|
-
this.name = "AgentFileChangeReportBudgetError";
|
|
28257
|
-
}
|
|
28258
|
-
reason;
|
|
28259
|
-
};
|
|
28260
|
-
var AgentFileChangeReportBudget = class {
|
|
28261
|
-
constructor(signal) {
|
|
28262
|
-
this.signal = signal;
|
|
28263
|
-
}
|
|
28264
|
-
signal;
|
|
28265
|
-
deadline = Date.now() + AGENT_FILE_CHANGE_REPORT_TIMEOUT_MS;
|
|
28266
|
-
async wait(operation) {
|
|
28267
|
-
void operation.catch(() => {
|
|
28268
|
-
});
|
|
28269
|
-
const immediateReason = this.stopReason();
|
|
28270
|
-
if (immediateReason !== null) {
|
|
28271
|
-
throw new AgentFileChangeReportBudgetError(immediateReason);
|
|
28272
|
-
}
|
|
28273
|
-
return await new Promise((resolve, reject) => {
|
|
28274
|
-
let settled = false;
|
|
28275
|
-
const finish = (action) => {
|
|
28276
|
-
if (settled) return;
|
|
28277
|
-
settled = true;
|
|
28278
|
-
clearTimeout(timeout);
|
|
28279
|
-
this.signal?.removeEventListener("abort", onAbort);
|
|
28280
|
-
action();
|
|
28281
|
-
};
|
|
28282
|
-
const onAbort = () => finish(() => reject(new AgentFileChangeReportBudgetError("cancelled")));
|
|
28283
|
-
const timeout = setTimeout(
|
|
28284
|
-
() => finish(() => reject(new AgentFileChangeReportBudgetError("timeout"))),
|
|
28285
|
-
Math.max(1, this.deadline - Date.now())
|
|
28286
|
-
);
|
|
28287
|
-
timeout.unref();
|
|
28288
|
-
this.signal?.addEventListener("abort", onAbort, { once: true });
|
|
28289
|
-
if (this.signal?.aborted) {
|
|
28290
|
-
onAbort();
|
|
28291
|
-
}
|
|
28292
|
-
void operation.then(
|
|
28293
|
-
(value) => finish(() => resolve(value)),
|
|
28294
|
-
(error48) => finish(() => reject(error48))
|
|
28295
|
-
);
|
|
28296
|
-
});
|
|
28297
|
-
}
|
|
28298
|
-
stopReason() {
|
|
28299
|
-
if (this.signal?.aborted) return "cancelled";
|
|
28300
|
-
if (Date.now() >= this.deadline) return "timeout";
|
|
28301
|
-
return null;
|
|
28302
|
-
}
|
|
28303
|
-
};
|
|
28304
28346
|
function buildPromptItems(prompt) {
|
|
28305
28347
|
return prompt.map((block) => {
|
|
28306
28348
|
switch (block.type) {
|
|
@@ -28415,6 +28457,16 @@ function mergeSandboxWorkspaceWriteRoots(config2, roots) {
|
|
|
28415
28457
|
}
|
|
28416
28458
|
};
|
|
28417
28459
|
}
|
|
28460
|
+
function forceGitRootTurnDiffPaths(config2) {
|
|
28461
|
+
const features = isJsonObject(config2["features"]) ? config2["features"] : {};
|
|
28462
|
+
return {
|
|
28463
|
+
...config2,
|
|
28464
|
+
features: {
|
|
28465
|
+
...features,
|
|
28466
|
+
cwd_relative_turn_diffs: false
|
|
28467
|
+
}
|
|
28468
|
+
};
|
|
28469
|
+
}
|
|
28418
28470
|
function addAdditionalDirectoriesToSandboxPolicy(sandboxPolicy, additionalDirectories) {
|
|
28419
28471
|
if (additionalDirectories.length === 0 || sandboxPolicy.type !== "workspaceWrite") {
|
|
28420
28472
|
return sandboxPolicy;
|
|
@@ -28455,12 +28507,12 @@ function mergeGatewayConfig(config2, gatewayConfig) {
|
|
|
28455
28507
|
return config2;
|
|
28456
28508
|
}
|
|
28457
28509
|
}
|
|
28458
|
-
var
|
|
28459
|
-
var CommandExecutionApprovalRequest = new
|
|
28460
|
-
var FileChangeApprovalRequest = new
|
|
28461
|
-
var PermissionsApprovalRequest = new
|
|
28462
|
-
var McpServerElicitationRequest = new
|
|
28463
|
-
var ToolRequestUserInputRequest = new
|
|
28510
|
+
var import_node3 = __toESM(require_main());
|
|
28511
|
+
var CommandExecutionApprovalRequest = new import_node3.RequestType("item/commandExecution/requestApproval");
|
|
28512
|
+
var FileChangeApprovalRequest = new import_node3.RequestType("item/fileChange/requestApproval");
|
|
28513
|
+
var PermissionsApprovalRequest = new import_node3.RequestType("item/permissions/requestApproval");
|
|
28514
|
+
var McpServerElicitationRequest = new import_node3.RequestType("mcpServer/elicitation/request");
|
|
28515
|
+
var ToolRequestUserInputRequest = new import_node3.RequestType("item/tool/requestUserInput");
|
|
28464
28516
|
var GOAL_RUNTIME_EFFECTS_GRACE_MS = 1e3;
|
|
28465
28517
|
var CodexAppServerClient = class {
|
|
28466
28518
|
connection;
|
|
@@ -28472,6 +28524,7 @@ var CodexAppServerClient = class {
|
|
|
28472
28524
|
pendingTurnCompletionResolvers = /* @__PURE__ */ new Map();
|
|
28473
28525
|
pendingCompactTurns = /* @__PURE__ */ new Map();
|
|
28474
28526
|
turnCompletionCaptures = /* @__PURE__ */ new Map();
|
|
28527
|
+
turnStartCaptures = /* @__PURE__ */ new Set();
|
|
28475
28528
|
turnRoutingCaptures = /* @__PURE__ */ new Map();
|
|
28476
28529
|
threadStatusCaptures = /* @__PURE__ */ new Map();
|
|
28477
28530
|
threadGoalUpdateCaptures = /* @__PURE__ */ new Map();
|
|
@@ -28516,6 +28569,7 @@ var CodexAppServerClient = class {
|
|
|
28516
28569
|
compact.turnId = serverNotification.params.turn.id;
|
|
28517
28570
|
compact.onTurnStarted?.(compact.turnId);
|
|
28518
28571
|
}
|
|
28572
|
+
this.recordTurnStarted(serverNotification.params.threadId, serverNotification.params.turn.id);
|
|
28519
28573
|
}
|
|
28520
28574
|
if (isThreadStatusChangedNotification(serverNotification)) {
|
|
28521
28575
|
this.recordThreadStatusChanged(serverNotification.params);
|
|
@@ -28632,21 +28686,51 @@ var CodexAppServerClient = class {
|
|
|
28632
28686
|
}
|
|
28633
28687
|
async runReview(params, onTurnStarted) {
|
|
28634
28688
|
const capturedCompletions = [];
|
|
28635
|
-
|
|
28689
|
+
let reviewThreadId = null;
|
|
28690
|
+
let reviewTurnId = null;
|
|
28691
|
+
const observedTurnStarts = [];
|
|
28692
|
+
const observedTurnStartKeys = /* @__PURE__ */ new Set();
|
|
28693
|
+
const completionCaptures = [];
|
|
28694
|
+
const startCaptures = [];
|
|
28695
|
+
const captureReviewCompletion = (event) => {
|
|
28636
28696
|
capturedCompletions.push(event);
|
|
28637
|
-
}
|
|
28697
|
+
};
|
|
28698
|
+
const captureReviewStart = (threadId, turnId) => {
|
|
28699
|
+
const key = `${threadId}\0${turnId}`;
|
|
28700
|
+
if (observedTurnStartKeys.has(key)) return;
|
|
28701
|
+
observedTurnStartKeys.add(key);
|
|
28702
|
+
const start = { threadId, turnId };
|
|
28703
|
+
if (reviewThreadId === null) {
|
|
28704
|
+
observedTurnStarts.push(start);
|
|
28705
|
+
return;
|
|
28706
|
+
}
|
|
28707
|
+
if (threadId === reviewThreadId && turnId !== reviewTurnId) {
|
|
28708
|
+
onTurnStarted?.(turnId, threadId);
|
|
28709
|
+
}
|
|
28710
|
+
};
|
|
28711
|
+
completionCaptures.push(this.captureTurnCompletions(params.threadId, captureReviewCompletion));
|
|
28712
|
+
startCaptures.push(this.captureTurnStarts(captureReviewStart));
|
|
28638
28713
|
try {
|
|
28639
28714
|
const reviewStarted = await this.reviewStart(params);
|
|
28640
|
-
|
|
28641
|
-
|
|
28715
|
+
reviewThreadId = reviewStarted.reviewThreadId;
|
|
28716
|
+
reviewTurnId = reviewStarted.turn.id;
|
|
28717
|
+
if (reviewThreadId !== params.threadId) {
|
|
28718
|
+
completionCaptures.push(this.captureTurnCompletions(reviewThreadId, captureReviewCompletion));
|
|
28719
|
+
}
|
|
28720
|
+
for (const start of observedTurnStarts) {
|
|
28721
|
+
if (start.threadId === reviewThreadId && start.turnId !== reviewTurnId) {
|
|
28722
|
+
onTurnStarted?.(start.turnId, start.threadId);
|
|
28723
|
+
}
|
|
28724
|
+
}
|
|
28725
|
+
const earlyCompletion = capturedCompletions.find((event) => event.threadId === reviewThreadId && event.turn.id === reviewTurnId);
|
|
28642
28726
|
if (earlyCompletion) {
|
|
28643
28727
|
return earlyCompletion;
|
|
28644
28728
|
}
|
|
28645
28729
|
const completion = this.awaitTurnCompleted(reviewStarted.reviewThreadId, reviewStarted.turn.id);
|
|
28646
|
-
releaseCapture();
|
|
28647
28730
|
return await completion;
|
|
28648
28731
|
} finally {
|
|
28649
|
-
releaseCapture();
|
|
28732
|
+
for (const releaseCapture of completionCaptures) releaseCapture();
|
|
28733
|
+
for (const releaseCapture of startCaptures) releaseCapture();
|
|
28650
28734
|
}
|
|
28651
28735
|
}
|
|
28652
28736
|
async runGoalSet(params, onTurnStarted, runtimeEffectsGraceMs = GOAL_RUNTIME_EFFECTS_GRACE_MS, onGoalSet) {
|
|
@@ -28852,9 +28936,6 @@ var CodexAppServerClient = class {
|
|
|
28852
28936
|
threadStaleTurns.add(turnId);
|
|
28853
28937
|
this.staleTurnIds.set(threadId, threadStaleTurns);
|
|
28854
28938
|
}
|
|
28855
|
-
async projectList(params) {
|
|
28856
|
-
return await this.sendRequest({ method: "project/list", params });
|
|
28857
|
-
}
|
|
28858
28939
|
async projectCreate(params) {
|
|
28859
28940
|
return await this.sendRequest({ method: "project/create", params });
|
|
28860
28941
|
}
|
|
@@ -28891,6 +28972,41 @@ var CodexAppServerClient = class {
|
|
|
28891
28972
|
async threadRead(params) {
|
|
28892
28973
|
return await this.sendRequest({ method: "thread/read", params });
|
|
28893
28974
|
}
|
|
28975
|
+
async threadTurnsList(params) {
|
|
28976
|
+
return await this.sendRequest({ method: "thread/turns/list", params });
|
|
28977
|
+
}
|
|
28978
|
+
async threadReadWithHistory(threadId) {
|
|
28979
|
+
const response = await this.threadRead({ threadId });
|
|
28980
|
+
if (response.thread.historyMode === "legacy") {
|
|
28981
|
+
return await this.threadRead({ threadId, includeTurns: true });
|
|
28982
|
+
}
|
|
28983
|
+
const turns = await this.threadReadHistory(threadId);
|
|
28984
|
+
return { ...response, thread: { ...response.thread, turns } };
|
|
28985
|
+
}
|
|
28986
|
+
async threadReadHistory(threadId, initialCursor = null) {
|
|
28987
|
+
const turns = [];
|
|
28988
|
+
const seenCursors = /* @__PURE__ */ new Set();
|
|
28989
|
+
if (initialCursor !== null) seenCursors.add(initialCursor);
|
|
28990
|
+
let cursor = initialCursor;
|
|
28991
|
+
do {
|
|
28992
|
+
const page = await this.threadTurnsList({
|
|
28993
|
+
threadId,
|
|
28994
|
+
cursor,
|
|
28995
|
+
limit: 50,
|
|
28996
|
+
sortDirection: "desc",
|
|
28997
|
+
itemsView: "full"
|
|
28998
|
+
});
|
|
28999
|
+
turns.push(...page.data);
|
|
29000
|
+
cursor = page.nextCursor;
|
|
29001
|
+
if (cursor !== null) {
|
|
29002
|
+
if (seenCursors.has(cursor)) {
|
|
29003
|
+
throw new Error("Codex returned a repeated thread history cursor");
|
|
29004
|
+
}
|
|
29005
|
+
seenCursors.add(cursor);
|
|
29006
|
+
}
|
|
29007
|
+
} while (cursor !== null);
|
|
29008
|
+
return turns.reverse();
|
|
29009
|
+
}
|
|
28894
29010
|
async threadArchive(params) {
|
|
28895
29011
|
return await this.sendRequest({ method: "thread/archive", params });
|
|
28896
29012
|
}
|
|
@@ -29037,11 +29153,7 @@ var CodexAppServerClient = class {
|
|
|
29037
29153
|
const threadResolvers = this.pendingTurnCompletionResolvers.get(event.threadId);
|
|
29038
29154
|
const entry = threadResolvers?.get(event.turn.id);
|
|
29039
29155
|
if (entry) {
|
|
29040
|
-
|
|
29041
|
-
if (threadResolvers.size === 0) {
|
|
29042
|
-
this.pendingTurnCompletionResolvers.delete(event.threadId);
|
|
29043
|
-
}
|
|
29044
|
-
entry.resolve(event);
|
|
29156
|
+
this.resolvePendingTurnCompletion(event.threadId, event.turn.id, event);
|
|
29045
29157
|
return;
|
|
29046
29158
|
}
|
|
29047
29159
|
const captures = this.turnCompletionCaptures.get(event.threadId);
|
|
@@ -29052,6 +29164,24 @@ var CodexAppServerClient = class {
|
|
|
29052
29164
|
capture(event);
|
|
29053
29165
|
}
|
|
29054
29166
|
}
|
|
29167
|
+
resolvePendingTurnCompletion(threadId, turnId, event) {
|
|
29168
|
+
const threadResolvers = this.pendingTurnCompletionResolvers.get(threadId);
|
|
29169
|
+
const entry = threadResolvers?.get(turnId);
|
|
29170
|
+
if (!entry) {
|
|
29171
|
+
return false;
|
|
29172
|
+
}
|
|
29173
|
+
threadResolvers.delete(turnId);
|
|
29174
|
+
if (threadResolvers.size === 0) {
|
|
29175
|
+
this.pendingTurnCompletionResolvers.delete(threadId);
|
|
29176
|
+
}
|
|
29177
|
+
entry.resolve(event);
|
|
29178
|
+
return true;
|
|
29179
|
+
}
|
|
29180
|
+
recordTurnStarted(threadId, turnId) {
|
|
29181
|
+
for (const capture of this.turnStartCaptures) {
|
|
29182
|
+
capture(threadId, turnId);
|
|
29183
|
+
}
|
|
29184
|
+
}
|
|
29055
29185
|
recordThreadStatusChanged(event) {
|
|
29056
29186
|
const captures = this.threadStatusCaptures.get(event.threadId);
|
|
29057
29187
|
if (!captures) {
|
|
@@ -29162,6 +29292,17 @@ var CodexAppServerClient = class {
|
|
|
29162
29292
|
}
|
|
29163
29293
|
};
|
|
29164
29294
|
}
|
|
29295
|
+
captureTurnStarts(capture) {
|
|
29296
|
+
this.turnStartCaptures.add(capture);
|
|
29297
|
+
let released = false;
|
|
29298
|
+
return () => {
|
|
29299
|
+
if (released) {
|
|
29300
|
+
return;
|
|
29301
|
+
}
|
|
29302
|
+
released = true;
|
|
29303
|
+
this.turnStartCaptures.delete(capture);
|
|
29304
|
+
};
|
|
29305
|
+
}
|
|
29165
29306
|
captureTurnRoutings(threadId, capture) {
|
|
29166
29307
|
const captures = this.turnRoutingCaptures.get(threadId) ?? /* @__PURE__ */ new Set();
|
|
29167
29308
|
captures.add(capture);
|
|
@@ -29321,6 +29462,10 @@ function extractTurnRouting(notification) {
|
|
|
29321
29462
|
}
|
|
29322
29463
|
var MODEL_CONFIG_ID = "model";
|
|
29323
29464
|
var REASONING_EFFORT_CONFIG_ID = "reasoning_effort";
|
|
29465
|
+
function formatModelDisplayName(displayName) {
|
|
29466
|
+
if (!/^gpt-/i.test(displayName)) return displayName;
|
|
29467
|
+
return displayName.replace(/^gpt-/i, "").split(/[-/]+/).filter(Boolean).map(capitalize2).join(" ");
|
|
29468
|
+
}
|
|
29324
29469
|
function capitalize2(value) {
|
|
29325
29470
|
return value.charAt(0).toUpperCase() + value.slice(1);
|
|
29326
29471
|
}
|
|
@@ -29339,19 +29484,20 @@ function findSupportedEffort(options, effort) {
|
|
|
29339
29484
|
if (!effort) return void 0;
|
|
29340
29485
|
return options.find((o) => o.reasoningEffort === effort)?.reasoningEffort;
|
|
29341
29486
|
}
|
|
29342
|
-
function createModelConfigOption(availableModels, currentBaseModelId) {
|
|
29487
|
+
function createModelConfigOption(availableModels, currentBaseModelId, recommendedModelId) {
|
|
29343
29488
|
const options = availableModels.map((model) => ({
|
|
29344
29489
|
value: model.id,
|
|
29345
|
-
name: model.displayName,
|
|
29490
|
+
name: formatModelDisplayName(model.displayName),
|
|
29346
29491
|
description: model.description
|
|
29347
29492
|
}));
|
|
29348
29493
|
if (!availableModels.some((model) => model.id === currentBaseModelId)) {
|
|
29349
29494
|
options.unshift({
|
|
29350
29495
|
value: currentBaseModelId,
|
|
29351
|
-
name: currentBaseModelId,
|
|
29496
|
+
name: formatModelDisplayName(currentBaseModelId),
|
|
29352
29497
|
description: null
|
|
29353
29498
|
});
|
|
29354
29499
|
}
|
|
29500
|
+
const recommendation = recommendedModelId && options.some((option) => option.value === recommendedModelId) ? recommendedModelId : void 0;
|
|
29355
29501
|
return {
|
|
29356
29502
|
id: MODEL_CONFIG_ID,
|
|
29357
29503
|
name: "Model",
|
|
@@ -29359,10 +29505,12 @@ function createModelConfigOption(availableModels, currentBaseModelId) {
|
|
|
29359
29505
|
category: "model",
|
|
29360
29506
|
type: "select",
|
|
29361
29507
|
currentValue: currentBaseModelId,
|
|
29362
|
-
options
|
|
29508
|
+
options,
|
|
29509
|
+
...recommendation ? { _meta: withAirMeta(void 0, AIR_RECOMMENDED_CONFIG_VALUE_KEY, recommendation) } : {}
|
|
29363
29510
|
};
|
|
29364
29511
|
}
|
|
29365
|
-
function createReasoningEffortConfigOption(supportedReasoningEfforts, currentEffort) {
|
|
29512
|
+
function createReasoningEffortConfigOption(supportedReasoningEfforts, currentEffort, recommendedEffort) {
|
|
29513
|
+
const recommendation = findSupportedEffort(supportedReasoningEfforts, recommendedEffort);
|
|
29366
29514
|
return {
|
|
29367
29515
|
id: REASONING_EFFORT_CONFIG_ID,
|
|
29368
29516
|
name: "Reasoning effort",
|
|
@@ -29374,7 +29522,8 @@ function createReasoningEffortConfigOption(supportedReasoningEfforts, currentEff
|
|
|
29374
29522
|
value: option.reasoningEffort,
|
|
29375
29523
|
name: reasoningEffortDisplayName(option.reasoningEffort),
|
|
29376
29524
|
description: option.description
|
|
29377
|
-
}))
|
|
29525
|
+
})),
|
|
29526
|
+
...recommendation ? { _meta: withAirMeta(void 0, AIR_RECOMMENDED_CONFIG_VALUE_KEY, recommendation) } : {}
|
|
29378
29527
|
};
|
|
29379
29528
|
}
|
|
29380
29529
|
var GOAL_OBJECTIVE_MAX_LENGTH = 4e3;
|
|
@@ -29563,7 +29712,7 @@ var CodexCommands = class {
|
|
|
29563
29712
|
}
|
|
29564
29713
|
case "compact": {
|
|
29565
29714
|
options.onTurnStartPending?.();
|
|
29566
|
-
options.
|
|
29715
|
+
options.onNativeCommandStarted?.();
|
|
29567
29716
|
try {
|
|
29568
29717
|
const turnCompleted = await this.runWithProcessCheck(
|
|
29569
29718
|
() => this.codexAcpClient.runCompact(sessionId, (turnId) => {
|
|
@@ -29572,7 +29721,7 @@ var CodexCommands = class {
|
|
|
29572
29721
|
);
|
|
29573
29722
|
return { handled: true, turnCompleted };
|
|
29574
29723
|
} finally {
|
|
29575
|
-
options.
|
|
29724
|
+
options.onNativeCommandFinished?.();
|
|
29576
29725
|
}
|
|
29577
29726
|
}
|
|
29578
29727
|
case "goal": {
|
|
@@ -29581,7 +29730,7 @@ var CodexCommands = class {
|
|
|
29581
29730
|
case "review": {
|
|
29582
29731
|
const target = this.buildReviewTarget(command.rest);
|
|
29583
29732
|
const turnCompleted = await this.runReviewCommand(sessionState, target, options);
|
|
29584
|
-
return { handled: true, turnCompleted };
|
|
29733
|
+
return { handled: true, turnCompleted, waitForGoalContinuation: false };
|
|
29585
29734
|
}
|
|
29586
29735
|
case "review-branch": {
|
|
29587
29736
|
if (command.rest.length === 0) {
|
|
@@ -29592,7 +29741,7 @@ var CodexCommands = class {
|
|
|
29592
29741
|
type: "baseBranch",
|
|
29593
29742
|
branch: command.rest
|
|
29594
29743
|
}, options);
|
|
29595
|
-
return { handled: true, turnCompleted };
|
|
29744
|
+
return { handled: true, turnCompleted, waitForGoalContinuation: false };
|
|
29596
29745
|
}
|
|
29597
29746
|
case "review-commit": {
|
|
29598
29747
|
if (command.rest.length === 0) {
|
|
@@ -29604,7 +29753,7 @@ var CodexCommands = class {
|
|
|
29604
29753
|
sha: command.rest,
|
|
29605
29754
|
title: null
|
|
29606
29755
|
}, options);
|
|
29607
|
-
return { handled: true, turnCompleted };
|
|
29756
|
+
return { handled: true, turnCompleted, waitForGoalContinuation: false };
|
|
29608
29757
|
}
|
|
29609
29758
|
case "status": {
|
|
29610
29759
|
await this.refreshRateLimits(sessionState);
|
|
@@ -29656,13 +29805,18 @@ var CodexCommands = class {
|
|
|
29656
29805
|
}
|
|
29657
29806
|
async runReviewCommand(sessionState, target, options) {
|
|
29658
29807
|
options.onTurnStartPending?.();
|
|
29659
|
-
|
|
29660
|
-
|
|
29661
|
-
|
|
29662
|
-
|
|
29663
|
-
|
|
29664
|
-
|
|
29665
|
-
|
|
29808
|
+
options.onNativeCommandStarted?.();
|
|
29809
|
+
try {
|
|
29810
|
+
return await this.runWithProcessCheck(() => this.codexAcpClient.runReview(
|
|
29811
|
+
sessionState.sessionId,
|
|
29812
|
+
target,
|
|
29813
|
+
(turnId, threadId) => {
|
|
29814
|
+
this.handleCommandTurnStarted(sessionState, options, turnId, threadId);
|
|
29815
|
+
}
|
|
29816
|
+
));
|
|
29817
|
+
} finally {
|
|
29818
|
+
options.onNativeCommandFinished?.();
|
|
29819
|
+
}
|
|
29666
29820
|
}
|
|
29667
29821
|
async runGoalCommand(sessionState, rest, options) {
|
|
29668
29822
|
const sessionId = sessionState.sessionId;
|
|
@@ -30175,14 +30329,14 @@ function parseJsonRecord(line) {
|
|
|
30175
30329
|
}
|
|
30176
30330
|
try {
|
|
30177
30331
|
const value = JSON.parse(line);
|
|
30178
|
-
return
|
|
30332
|
+
return asRecord3(value);
|
|
30179
30333
|
} catch {
|
|
30180
30334
|
return null;
|
|
30181
30335
|
}
|
|
30182
30336
|
}
|
|
30183
30337
|
function extractResponseItem(record2) {
|
|
30184
30338
|
if (record2["type"] === "response_item") {
|
|
30185
|
-
return
|
|
30339
|
+
return asRecord3(record2["payload"]);
|
|
30186
30340
|
}
|
|
30187
30341
|
const itemType = record2["type"];
|
|
30188
30342
|
if (typeof itemType === "string" && isLegacyResponseItemType(itemType)) {
|
|
@@ -30216,7 +30370,7 @@ function createEventMsgUpdates(record2) {
|
|
|
30216
30370
|
if (record2["type"] !== "event_msg") {
|
|
30217
30371
|
return null;
|
|
30218
30372
|
}
|
|
30219
|
-
const payload =
|
|
30373
|
+
const payload = asRecord3(record2["payload"]);
|
|
30220
30374
|
if (!payload) {
|
|
30221
30375
|
return [];
|
|
30222
30376
|
}
|
|
@@ -30264,7 +30418,7 @@ function imageBlocks(images) {
|
|
|
30264
30418
|
if (typeof image === "string") {
|
|
30265
30419
|
return [{ type: "text", text: `[@image](${image})` }];
|
|
30266
30420
|
}
|
|
30267
|
-
const record2 =
|
|
30421
|
+
const record2 = asRecord3(image);
|
|
30268
30422
|
const path10 = record2 ? stringValue(record2["path"]) ?? stringValue(record2["url"]) : null;
|
|
30269
30423
|
return path10 ? [{ type: "text", text: `[@image](${path10})` }] : [];
|
|
30270
30424
|
});
|
|
@@ -30274,7 +30428,7 @@ function contentBlocksFromResponseContent(content) {
|
|
|
30274
30428
|
return [];
|
|
30275
30429
|
}
|
|
30276
30430
|
return content.flatMap((entry) => {
|
|
30277
|
-
const record2 =
|
|
30431
|
+
const record2 = asRecord3(entry);
|
|
30278
30432
|
if (!record2) {
|
|
30279
30433
|
return [];
|
|
30280
30434
|
}
|
|
@@ -30303,7 +30457,7 @@ function textParts(value) {
|
|
|
30303
30457
|
if (typeof entry === "string") {
|
|
30304
30458
|
return entry.length > 0 ? [entry] : [];
|
|
30305
30459
|
}
|
|
30306
|
-
const record2 =
|
|
30460
|
+
const record2 = asRecord3(entry);
|
|
30307
30461
|
if (!record2) {
|
|
30308
30462
|
return [];
|
|
30309
30463
|
}
|
|
@@ -30317,6 +30471,7 @@ function createFunctionCallUpdate(item) {
|
|
|
30317
30471
|
if (!toolCallId || !name) {
|
|
30318
30472
|
return null;
|
|
30319
30473
|
}
|
|
30474
|
+
const toolName = functionToolName(name, stringValue(item["namespace"]));
|
|
30320
30475
|
const isExecCommand = name === "exec_command";
|
|
30321
30476
|
const args = parseFunctionArguments(item["arguments"]);
|
|
30322
30477
|
const command = isExecCommand ? commandFromFunctionArguments(args) : null;
|
|
@@ -30324,7 +30479,10 @@ function createFunctionCallUpdate(item) {
|
|
|
30324
30479
|
const commandAction = command ? inferCommandAction(command, cwd) : null;
|
|
30325
30480
|
if (commandAction) {
|
|
30326
30481
|
return {
|
|
30327
|
-
update:
|
|
30482
|
+
update: {
|
|
30483
|
+
...createCommandActionEvent(toolCallId, "inProgress", cwd, commandAction),
|
|
30484
|
+
name: toolName
|
|
30485
|
+
},
|
|
30328
30486
|
usesTerminal: false,
|
|
30329
30487
|
isExecCommand
|
|
30330
30488
|
};
|
|
@@ -30332,6 +30490,7 @@ function createFunctionCallUpdate(item) {
|
|
|
30332
30490
|
const update = {
|
|
30333
30491
|
sessionUpdate: "tool_call",
|
|
30334
30492
|
toolCallId,
|
|
30493
|
+
name: toolName,
|
|
30335
30494
|
kind: toolKindForFunctionCall(name),
|
|
30336
30495
|
title: titleForFunctionCall(name, args),
|
|
30337
30496
|
status: "in_progress",
|
|
@@ -30395,7 +30554,7 @@ function parseFunctionArguments(value) {
|
|
|
30395
30554
|
}
|
|
30396
30555
|
function rawInputForFunctionCall(name, args) {
|
|
30397
30556
|
if (name === "exec_command") {
|
|
30398
|
-
const record2 =
|
|
30557
|
+
const record2 = asRecord3(args);
|
|
30399
30558
|
if (record2) {
|
|
30400
30559
|
return {
|
|
30401
30560
|
command: stringValue(record2["cmd"]) ?? stringValue(record2["command"]),
|
|
@@ -30442,14 +30601,14 @@ function functionCallUsesTerminal(item) {
|
|
|
30442
30601
|
return item["name"] === "exec_command";
|
|
30443
30602
|
}
|
|
30444
30603
|
function commandFromFunctionArguments(args) {
|
|
30445
|
-
const record2 =
|
|
30604
|
+
const record2 = asRecord3(args);
|
|
30446
30605
|
if (!record2) {
|
|
30447
30606
|
return null;
|
|
30448
30607
|
}
|
|
30449
30608
|
return stringValue(record2["cmd"]) ?? stringValue(record2["command"]);
|
|
30450
30609
|
}
|
|
30451
30610
|
function cwdFromFunctionArguments(args) {
|
|
30452
|
-
const record2 =
|
|
30611
|
+
const record2 = asRecord3(args);
|
|
30453
30612
|
if (!record2) {
|
|
30454
30613
|
return "";
|
|
30455
30614
|
}
|
|
@@ -30921,7 +31080,7 @@ function outputText(output) {
|
|
|
30921
31080
|
return "";
|
|
30922
31081
|
}
|
|
30923
31082
|
return output.flatMap((entry) => {
|
|
30924
|
-
const record2 =
|
|
31083
|
+
const record2 = asRecord3(entry);
|
|
30925
31084
|
if (!record2) {
|
|
30926
31085
|
return [];
|
|
30927
31086
|
}
|
|
@@ -30937,7 +31096,7 @@ function outputText(output) {
|
|
|
30937
31096
|
}).join("\n");
|
|
30938
31097
|
}
|
|
30939
31098
|
function parseExitCode(rawOutput, output) {
|
|
30940
|
-
const record2 =
|
|
31099
|
+
const record2 = asRecord3(rawOutput);
|
|
30941
31100
|
if (record2) {
|
|
30942
31101
|
const exitCode2 = numberValue(record2["exit_code"]) ?? numberValue(record2["exitCode"]);
|
|
30943
31102
|
if (exitCode2 !== null) {
|
|
@@ -30968,7 +31127,7 @@ function looksLikeCommandFailure(output) {
|
|
|
30968
31127
|
}
|
|
30969
31128
|
return /(^|\n)(Error|Failed|Command failed|Sandbox error|No such file or directory|Permission denied|Operation not permitted|ENOENT|EACCES)(:|\b)/i.test(trimmed);
|
|
30970
31129
|
}
|
|
30971
|
-
function
|
|
31130
|
+
function asRecord3(value) {
|
|
30972
31131
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
30973
31132
|
return null;
|
|
30974
31133
|
}
|
|
@@ -31455,12 +31614,7 @@ function clientSupportsTypedSessionFailures(capabilities) {
|
|
|
31455
31614
|
function clientSupportsAgentFileChangeReports(capabilities) {
|
|
31456
31615
|
return clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY);
|
|
31457
31616
|
}
|
|
31458
|
-
var CodexAcpServer = class
|
|
31459
|
-
static MODEL_NAME_TOKEN_OVERRIDES = {
|
|
31460
|
-
gpt: "GPT",
|
|
31461
|
-
mini: "Mini",
|
|
31462
|
-
codex: "Codex"
|
|
31463
|
-
};
|
|
31617
|
+
var CodexAcpServer = class {
|
|
31464
31618
|
codexAcpClient;
|
|
31465
31619
|
connection;
|
|
31466
31620
|
defaultAuthRequest;
|
|
@@ -31582,7 +31736,8 @@ var CodexAcpServer = class _CodexAcpServer {
|
|
|
31582
31736
|
AIR_SESSION_FAILURE_KEY,
|
|
31583
31737
|
AIR_AGENT_FILE_CHANGE_REPORT_KEY,
|
|
31584
31738
|
AIR_NATIVE_SUBAGENT_SESSIONS_KEY,
|
|
31585
|
-
AIR_ASYNC_TASKS_KEY
|
|
31739
|
+
AIR_ASYNC_TASKS_KEY,
|
|
31740
|
+
AIR_RECOMMENDED_CONFIG_VALUE_KEY
|
|
31586
31741
|
]
|
|
31587
31742
|
}
|
|
31588
31743
|
}
|
|
@@ -32711,7 +32866,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
32711
32866
|
return { outcome: "injected" };
|
|
32712
32867
|
}
|
|
32713
32868
|
}
|
|
32714
|
-
|
|
32869
|
+
throw RequestError.invalidRequest("No active Codex turn to steer");
|
|
32715
32870
|
}
|
|
32716
32871
|
/**
|
|
32717
32872
|
* Rejects a steering prompt whose content the active model cannot accept
|
|
@@ -32906,14 +33061,24 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
32906
33061
|
}
|
|
32907
33062
|
createSessionConfigOptions(sessionState) {
|
|
32908
33063
|
const currentModelId = ModelId.fromString(sessionState.currentModelId);
|
|
33064
|
+
const useRecommendedValue = clientSupportsAirCapability(
|
|
33065
|
+
this.clientCapabilities,
|
|
33066
|
+
AIR_RECOMMENDED_CONFIG_VALUE_KEY
|
|
33067
|
+
);
|
|
33068
|
+
const currentModel = this.findCurrentModel(sessionState.availableModels, sessionState.currentModelId);
|
|
33069
|
+
const recommendedModelId = useRecommendedValue ? sessionState.availableModels.find((model) => model.isDefault)?.id : void 0;
|
|
32909
33070
|
const configOptions = [
|
|
32910
33071
|
sessionState.agentMode.toConfigOption(),
|
|
32911
33072
|
createCollaborationModeConfigOption(sessionState.collaborationMode),
|
|
32912
|
-
createModelConfigOption(sessionState.availableModels, currentModelId.model)
|
|
33073
|
+
createModelConfigOption(sessionState.availableModels, currentModelId.model, recommendedModelId)
|
|
32913
33074
|
];
|
|
32914
33075
|
if (sessionState.supportedReasoningEfforts.length > 0) {
|
|
32915
33076
|
configOptions.push(
|
|
32916
|
-
createReasoningEffortConfigOption(
|
|
33077
|
+
createReasoningEffortConfigOption(
|
|
33078
|
+
sessionState.supportedReasoningEfforts,
|
|
33079
|
+
currentModelId.effort,
|
|
33080
|
+
useRecommendedValue ? currentModel?.defaultReasoningEffort : void 0
|
|
33081
|
+
)
|
|
32917
33082
|
);
|
|
32918
33083
|
}
|
|
32919
33084
|
if (sessionState.currentModelSupportsFast) {
|
|
@@ -33021,14 +33186,11 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33021
33186
|
const modelId = ModelId.fromString(currentModelId);
|
|
33022
33187
|
return models.find((m) => m.id === modelId.model);
|
|
33023
33188
|
}
|
|
33024
|
-
normalizeModelDisplayName(displayName) {
|
|
33025
|
-
return displayName.split("-").map((token) => _CodexAcpServer.MODEL_NAME_TOKEN_OVERRIDES[token.toLowerCase()] ?? token).join("-");
|
|
33026
|
-
}
|
|
33027
33189
|
createModelState(availableModels, selectedModelId) {
|
|
33028
33190
|
const allowedModels = availableModels.flatMap(
|
|
33029
33191
|
(model) => model.supportedReasoningEfforts.map((effort) => ({
|
|
33030
33192
|
modelId: ModelId.fromComponents(model, effort.reasoningEffort).toString(),
|
|
33031
|
-
name: `${
|
|
33193
|
+
name: `${formatModelDisplayName(model.displayName)} (${effort.reasoningEffort})`,
|
|
33032
33194
|
description: `${model.description} ${effort.description}`
|
|
33033
33195
|
}))
|
|
33034
33196
|
);
|
|
@@ -33307,24 +33469,19 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33307
33469
|
}
|
|
33308
33470
|
});
|
|
33309
33471
|
}
|
|
33310
|
-
async publishAgentFileChangeReport(sessionState, turnId, request, unavailableReason,
|
|
33472
|
+
async publishAgentFileChangeReport(sessionState, turnId, request, unavailableReason, turnDiff, workspace) {
|
|
33311
33473
|
let report;
|
|
33312
33474
|
try {
|
|
33313
|
-
report = turnId === null ? createUnavailableAgentFileChangeReport(request.requestId, unavailableReason) :
|
|
33314
|
-
sessionId: sessionState.sessionId,
|
|
33315
|
-
turnId,
|
|
33316
|
-
// The client owns request-id correlation and duplicate suppression. The wrapper
|
|
33317
|
-
// stays stateless so a retried ACP prompt still receives a terminal report.
|
|
33318
|
-
requestId: request.requestId,
|
|
33319
|
-
workspace: {
|
|
33320
|
-
cwd: sessionState.cwd,
|
|
33321
|
-
additionalDirectories: sessionState.additionalDirectories
|
|
33322
|
-
},
|
|
33323
|
-
signal
|
|
33324
|
-
});
|
|
33475
|
+
report = turnId === null ? createUnavailableAgentFileChangeReport(request.requestId, unavailableReason) : createReportedAgentFileChangeReport(request.requestId, turnDiff, workspace);
|
|
33325
33476
|
} catch (error48) {
|
|
33326
|
-
logger.error(
|
|
33327
|
-
|
|
33477
|
+
logger.error(
|
|
33478
|
+
error48 instanceof AgentFileChangeReportError ? "Agent file-change report unavailable" : "Agent file-change report failed unexpectedly",
|
|
33479
|
+
error48
|
|
33480
|
+
);
|
|
33481
|
+
report = createUnavailableAgentFileChangeReport(
|
|
33482
|
+
request.requestId,
|
|
33483
|
+
error48 instanceof AgentFileChangeReportError ? error48.reason : "providerError"
|
|
33484
|
+
);
|
|
33328
33485
|
}
|
|
33329
33486
|
try {
|
|
33330
33487
|
const session = new ACPSessionConnection(this.connection, sessionState.sessionId);
|
|
@@ -33624,7 +33781,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33624
33781
|
signal: abortController.signal,
|
|
33625
33782
|
currentTurn: null,
|
|
33626
33783
|
hasCompletedTurn: false,
|
|
33627
|
-
|
|
33784
|
+
nativeCommandInFlight: false,
|
|
33628
33785
|
requestCancel: () => {
|
|
33629
33786
|
if (abortController.signal.aborted) {
|
|
33630
33787
|
return;
|
|
@@ -33655,6 +33812,10 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33655
33812
|
this.activePrompts.set(sessionId, activePrompt);
|
|
33656
33813
|
return activePrompt;
|
|
33657
33814
|
}
|
|
33815
|
+
setActivePromptTurn(activePrompt, turn) {
|
|
33816
|
+
activePrompt.hasCompletedTurn = false;
|
|
33817
|
+
activePrompt.currentTurn = turn;
|
|
33818
|
+
}
|
|
33658
33819
|
clearPendingSteers(sessionId, activePrompt) {
|
|
33659
33820
|
const pending = this.pendingSteers.get(sessionId);
|
|
33660
33821
|
if (!pending) return;
|
|
@@ -33689,7 +33850,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33689
33850
|
}
|
|
33690
33851
|
cancelBeforeTurnStarted(activePrompt) {
|
|
33691
33852
|
return activePrompt.cancelSignal.then(() => {
|
|
33692
|
-
if (activePrompt.currentTurn === null && !activePrompt.
|
|
33853
|
+
if (activePrompt.currentTurn === null && !activePrompt.nativeCommandInFlight) {
|
|
33693
33854
|
return null;
|
|
33694
33855
|
}
|
|
33695
33856
|
return new Promise(() => {
|
|
@@ -33758,7 +33919,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33758
33919
|
}
|
|
33759
33920
|
}
|
|
33760
33921
|
interruptLateStartedTurn(turn, activePrompt) {
|
|
33761
|
-
if (activePrompt.
|
|
33922
|
+
if (activePrompt.nativeCommandInFlight) {
|
|
33762
33923
|
this.codexAcpClient.markTurnStale(turn);
|
|
33763
33924
|
void this.requestTurnInterrupt(turn, "Cancel");
|
|
33764
33925
|
return;
|
|
@@ -33837,6 +33998,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33837
33998
|
const sessionState = this.getSessionState(params.sessionId);
|
|
33838
33999
|
const agentFileChangeReportRequest = clientSupportsAgentFileChangeReports(this.clientCapabilities) ? parseAgentFileChangeReportRequest(params._meta) : null;
|
|
33839
34000
|
const goalPromptControl = parseGoalPromptControl(params._meta);
|
|
34001
|
+
const agentFileChangeWorkspace = agentFileChangeReportRequest === null ? null : captureAgentFileChangeWorkspace(sessionState.cwd, sessionState.additionalDirectories);
|
|
33840
34002
|
let agentFileChangeReportTurnId = null;
|
|
33841
34003
|
let agentFileChangeReportUnavailableReason = "providerError";
|
|
33842
34004
|
let promptWasCancelled = false;
|
|
@@ -33886,7 +34048,8 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33886
34048
|
clientSupportsTypedSessionFailures(this.clientCapabilities),
|
|
33887
34049
|
this.sessionFailureEpoch,
|
|
33888
34050
|
sessionState.subagents,
|
|
33889
|
-
(accountUpdated) => this.handleAccountUpdated(accountUpdated)
|
|
34051
|
+
(accountUpdated) => this.handleAccountUpdated(accountUpdated),
|
|
34052
|
+
agentFileChangeReportRequest !== null
|
|
33890
34053
|
);
|
|
33891
34054
|
eventHandler = promptEventHandler;
|
|
33892
34055
|
const permissionLifecycle = this.permissionLifecycleContext(sessionState);
|
|
@@ -33913,7 +34076,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33913
34076
|
goalLifecycle.observe(event);
|
|
33914
34077
|
if (event.method === "turn/started" && event.params.threadId === params.sessionId) {
|
|
33915
34078
|
const turn = { threadId: params.sessionId, turnId: event.params.turn.id };
|
|
33916
|
-
activePrompt
|
|
34079
|
+
this.setActivePromptTurn(activePrompt, turn);
|
|
33917
34080
|
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
33918
34081
|
this.interruptLateStartedTurn(turn, activePrompt);
|
|
33919
34082
|
return;
|
|
@@ -33921,7 +34084,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33921
34084
|
recoverableSessionFailure = sessionState.sessionFailure;
|
|
33922
34085
|
promptNotificationsActive = true;
|
|
33923
34086
|
}
|
|
33924
|
-
if (event.method === "turn/completed" && event.params.threadId === params.sessionId && activePrompt.currentTurn?.turnId === event.params.turn.id) {
|
|
34087
|
+
if (event.method === "turn/completed" && event.params.threadId === params.sessionId && activePrompt.currentTurn?.threadId === event.params.threadId && activePrompt.currentTurn.turnId === event.params.turn.id) {
|
|
33925
34088
|
activePrompt.currentTurn = null;
|
|
33926
34089
|
activePrompt.hasCompletedTurn = true;
|
|
33927
34090
|
}
|
|
@@ -33932,7 +34095,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33932
34095
|
await promptEventHandler.handleSessionScopedNotification(event);
|
|
33933
34096
|
return;
|
|
33934
34097
|
}
|
|
33935
|
-
const completesActiveTurn = event.method === "turn/completed" && event.params.threadId === sessionState.sessionId && event.params.
|
|
34098
|
+
const completesActiveTurn = event.method === "turn/completed" && event.params.threadId === sessionState.sessionId && activePrompt.currentTurn?.threadId === event.params.threadId && activePrompt.currentTurn.turnId === event.params.turn.id;
|
|
33936
34099
|
await promptEventHandler.handleNotification(event);
|
|
33937
34100
|
if (completesActiveTurn) {
|
|
33938
34101
|
promptNotificationsActive = false;
|
|
@@ -33955,7 +34118,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33955
34118
|
onTurnStarted: (turnId, threadId) => {
|
|
33956
34119
|
const turn = { threadId, turnId };
|
|
33957
34120
|
if (threadId === params.sessionId) goalLifecycle.startTurn(turnId);
|
|
33958
|
-
activePrompt
|
|
34121
|
+
this.setActivePromptTurn(activePrompt, turn);
|
|
33959
34122
|
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
33960
34123
|
this.interruptLateStartedTurn(turn, activePrompt);
|
|
33961
34124
|
return;
|
|
@@ -33964,11 +34127,11 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33964
34127
|
pendingTurnStart?.resolve(turnId);
|
|
33965
34128
|
onTurnStarted?.();
|
|
33966
34129
|
},
|
|
33967
|
-
|
|
33968
|
-
activePrompt.
|
|
34130
|
+
onNativeCommandStarted: () => {
|
|
34131
|
+
activePrompt.nativeCommandInFlight = true;
|
|
33969
34132
|
},
|
|
33970
|
-
|
|
33971
|
-
activePrompt.
|
|
34133
|
+
onNativeCommandFinished: () => {
|
|
34134
|
+
activePrompt.nativeCommandInFlight = false;
|
|
33972
34135
|
},
|
|
33973
34136
|
setConfigOption: async (configId, value) => {
|
|
33974
34137
|
await this.applySessionConfigOption(sessionState, {
|
|
@@ -33998,7 +34161,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
33998
34161
|
return cancelledPromptResponse();
|
|
33999
34162
|
}
|
|
34000
34163
|
if (commandResult.handled) {
|
|
34001
|
-
if (commandResult.turnCompleted) {
|
|
34164
|
+
if (commandResult.turnCompleted && commandResult.waitForGoalContinuation !== false) {
|
|
34002
34165
|
await this.codexAcpClient.waitForSessionNotifications(params.sessionId);
|
|
34003
34166
|
const firstCommandTurn = commandResult.turnCompleted;
|
|
34004
34167
|
const completed = await this.runWithProcessCheck(() => Promise.race([
|
|
@@ -34084,7 +34247,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
34084
34247
|
onTurnStarted?.();
|
|
34085
34248
|
return;
|
|
34086
34249
|
}
|
|
34087
|
-
activePrompt
|
|
34250
|
+
this.setActivePromptTurn(activePrompt, turn);
|
|
34088
34251
|
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
34089
34252
|
this.interruptLateStartedTurn(turn, activePrompt);
|
|
34090
34253
|
return;
|
|
@@ -34183,7 +34346,7 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
34183
34346
|
(turnId) => {
|
|
34184
34347
|
const turn = { threadId: params.sessionId, turnId };
|
|
34185
34348
|
if (!goalLifecycle.startSubmittedTurn(turnId)) return;
|
|
34186
|
-
activePrompt
|
|
34349
|
+
this.setActivePromptTurn(activePrompt, turn);
|
|
34187
34350
|
if (this.promptShouldStop(params.sessionId, activePrompt)) {
|
|
34188
34351
|
this.interruptLateStartedTurn(turn, activePrompt);
|
|
34189
34352
|
return;
|
|
@@ -34306,13 +34469,21 @@ Check ${configPath} and project .codex directories, especially their config.toml
|
|
|
34306
34469
|
} catch (error48) {
|
|
34307
34470
|
logger.error("Failed to publish terminal subagent state during prompt cleanup", error48);
|
|
34308
34471
|
}
|
|
34309
|
-
if (agentFileChangeReportRequest !== null) {
|
|
34472
|
+
if (agentFileChangeReportRequest !== null && agentFileChangeWorkspace !== null) {
|
|
34473
|
+
if (promptWasCancelled || activePrompt.signal.aborted || this.sessionIsClosing(params.sessionId)) {
|
|
34474
|
+
agentFileChangeReportTurnId = null;
|
|
34475
|
+
agentFileChangeReportUnavailableReason = "cancelled";
|
|
34476
|
+
} else if (agentFileChangeReportTurnId !== null && eventHandler?.isTurnDiffOversized(agentFileChangeReportTurnId)) {
|
|
34477
|
+
agentFileChangeReportTurnId = null;
|
|
34478
|
+
agentFileChangeReportUnavailableReason = "invalidOutput";
|
|
34479
|
+
}
|
|
34310
34480
|
await this.publishAgentFileChangeReport(
|
|
34311
34481
|
sessionState,
|
|
34312
34482
|
agentFileChangeReportTurnId,
|
|
34313
34483
|
agentFileChangeReportRequest,
|
|
34314
34484
|
agentFileChangeReportUnavailableReason,
|
|
34315
|
-
|
|
34485
|
+
agentFileChangeReportTurnId === null || eventHandler === null ? "" : eventHandler.getTurnDiff(agentFileChangeReportTurnId),
|
|
34486
|
+
agentFileChangeWorkspace
|
|
34316
34487
|
);
|
|
34317
34488
|
}
|
|
34318
34489
|
logger.log("Prompt completed", { sessionId: params.sessionId });
|
|
@@ -34427,7 +34598,7 @@ ${stderr}` : "";
|
|
|
34427
34598
|
return;
|
|
34428
34599
|
}
|
|
34429
34600
|
const activePrompt = this.activePrompts.get(params.sessionId);
|
|
34430
|
-
if (activePrompt?.
|
|
34601
|
+
if (activePrompt?.nativeCommandInFlight) {
|
|
34431
34602
|
activePrompt.requestCancel();
|
|
34432
34603
|
if (activePrompt.currentTurn === null) return;
|
|
34433
34604
|
}
|