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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +454 -411
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -34722,6 +34722,344 @@ var NeutralSessionFailureLedger = class {
34722
34722
  }
34723
34723
  };
34724
34724
 
34725
+ // src/AgentFileChangeReport.ts
34726
+ import fs2 from "node:fs";
34727
+ import path5 from "node:path";
34728
+ var AGENT_FILE_CHANGE_REPORT_VERSION = 1;
34729
+ var AGENT_FILE_CHANGE_REPORT_MAX_PATHS = 1024;
34730
+ var AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH = 4096;
34731
+ var AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES = 256 * 1024;
34732
+ var AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES = 8 * 1024 * 1024;
34733
+ var NEUTRAL_AGENT_FILE_CHANGE_REPORT_META_KEY = "agentFileChangeReport";
34734
+ var NEUTRAL_AGENT_FILE_CHANGE_REPORT_REQUEST_META_KEY = "agentFileChangeReportRequest";
34735
+ 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.";
34736
+ function captureAgentFileChangeWorkspace(cwd, additionalDirectories) {
34737
+ const lexicalCwd = parseWorkspaceRoot(cwd);
34738
+ return {
34739
+ cwd,
34740
+ additionalDirectories: [...additionalDirectories],
34741
+ diffRoot: lexicalCwd === null ? cwd : findDiffDisplayRoot(lexicalCwd).value
34742
+ };
34743
+ }
34744
+ function neutralAgentFileChangeReportCapability() {
34745
+ return { version: AGENT_FILE_CHANGE_REPORT_VERSION };
34746
+ }
34747
+ function clientRequestsNeutralAgentFileChangeReport(capabilities) {
34748
+ const declared = asRecord2(capabilities?._meta?.[NEUTRAL_AGENT_FILE_CHANGE_REPORT_META_KEY]);
34749
+ const version2 = declared?.["version"];
34750
+ return typeof version2 === "number" && Number.isInteger(version2) && version2 >= 1;
34751
+ }
34752
+ function parseAgentFileChangeReportRequest(meta3) {
34753
+ const jetbrains = asRecord2(meta3?.[JETBRAINS_META_KEY]);
34754
+ const air = asRecord2(jetbrains?.[AIR_META_KEY]);
34755
+ return validateAgentFileChangeReportRequest(air?.[AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY]);
34756
+ }
34757
+ function parseNeutralAgentFileChangeReportRequest(meta3) {
34758
+ return validateAgentFileChangeReportRequest(meta3?.[NEUTRAL_AGENT_FILE_CHANGE_REPORT_REQUEST_META_KEY]);
34759
+ }
34760
+ function agentFileChangeReportRequestFor(format, meta3) {
34761
+ switch (format) {
34762
+ case "none":
34763
+ return null;
34764
+ case "air":
34765
+ return parseAgentFileChangeReportRequest(meta3);
34766
+ case "neutral":
34767
+ return parseNeutralAgentFileChangeReportRequest(meta3);
34768
+ }
34769
+ }
34770
+ function agentFileChangeReportMeta(format, report) {
34771
+ if (format === "neutral") {
34772
+ return { [NEUTRAL_AGENT_FILE_CHANGE_REPORT_META_KEY]: report };
34773
+ }
34774
+ return {
34775
+ [JETBRAINS_META_KEY]: {
34776
+ [AIR_META_KEY]: {
34777
+ [AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
34778
+ [AIR_AGENT_FILE_CHANGE_REPORT_KEY]: report
34779
+ }
34780
+ }
34781
+ };
34782
+ }
34783
+ function validateAgentFileChangeReportRequest(value) {
34784
+ const request = asRecord2(value);
34785
+ if (request === null || !hasOnlyKeys(request, ["version", "requestId"]) || request["version"] !== AGENT_FILE_CHANGE_REPORT_VERSION) {
34786
+ return null;
34787
+ }
34788
+ const requestId = request["requestId"];
34789
+ if (typeof requestId !== "string" || !/^[A-Za-z0-9._:-]{1,128}$/.test(requestId)) {
34790
+ return null;
34791
+ }
34792
+ return { version: AGENT_FILE_CHANGE_REPORT_VERSION, requestId };
34793
+ }
34794
+ function createReportedAgentFileChangeReport(requestId, diff, workspace) {
34795
+ if (Buffer.byteLength(diff, "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES) {
34796
+ throw new AgentFileChangeReportError("invalidOutput", "The turn diff exceeds the parser input limit");
34797
+ }
34798
+ const parsedReport = parseTurnDiff(diff);
34799
+ const normalized = normalizeFileChangeReport(parsedReport, workspace);
34800
+ return fitReportedAgentFileChangeReport({
34801
+ version: AGENT_FILE_CHANGE_REPORT_VERSION,
34802
+ requestId,
34803
+ status: "reported",
34804
+ ...normalized
34805
+ });
34806
+ }
34807
+ function createUnavailableAgentFileChangeReport(requestId, reason) {
34808
+ return {
34809
+ version: AGENT_FILE_CHANGE_REPORT_VERSION,
34810
+ requestId,
34811
+ status: "unavailable",
34812
+ reason
34813
+ };
34814
+ }
34815
+ var AgentFileChangeReportError = class extends Error {
34816
+ reason;
34817
+ constructor(reason, message) {
34818
+ super(message);
34819
+ this.name = "AgentFileChangeReportError";
34820
+ this.reason = reason;
34821
+ }
34822
+ };
34823
+ function parseTurnDiff(diff) {
34824
+ if (diff.trim() === "") {
34825
+ return { paths: [], complete: false, uncertainty: TURN_DIFF_UNCERTAINTY };
34826
+ }
34827
+ let patches;
34828
+ try {
34829
+ patches = parsePatch(diff);
34830
+ } catch (error62) {
34831
+ throw new AgentFileChangeReportError(
34832
+ "invalidOutput",
34833
+ `The turn diff is not valid unified diff: ${error62 instanceof Error ? error62.message : String(error62)}`
34834
+ );
34835
+ }
34836
+ if (patches.length === 0) {
34837
+ throw new AgentFileChangeReportError("invalidOutput", "The turn diff contains no parseable file patches");
34838
+ }
34839
+ const rawFileHeaders = extractRawFileHeaders(diff);
34840
+ const paths = [];
34841
+ for (const [index, patch] of patches.entries()) {
34842
+ const rawHeaders = rawFileHeaders[index];
34843
+ const oldPath = normalizeDiffPath(selectLosslessFileName(rawHeaders?.oldFileName, patch.oldFileName));
34844
+ const newPath = normalizeDiffPath(selectLosslessFileName(rawHeaders?.newFileName, patch.newFileName));
34845
+ if (oldPath === null && newPath === null) {
34846
+ throw new AgentFileChangeReportError("invalidOutput", "The turn diff contains a patch without a file path");
34847
+ }
34848
+ if (oldPath !== null) paths.push(oldPath);
34849
+ if (newPath !== null) paths.push(newPath);
34850
+ }
34851
+ return { paths, complete: false, uncertainty: TURN_DIFF_UNCERTAINTY };
34852
+ }
34853
+ function extractRawFileHeaders(diff) {
34854
+ return diff.split(/(?=^diff --git )/m).filter((section) => section.trim() !== "").map((section) => {
34855
+ const lines = section.split(/\r?\n/);
34856
+ for (let index = 0; index < lines.length; index += 1) {
34857
+ const line = lines[index];
34858
+ if (line?.startsWith("@@ ")) return null;
34859
+ const nextLine = lines[index + 1];
34860
+ if (line?.startsWith("--- ") && nextLine?.startsWith("+++ ")) {
34861
+ return {
34862
+ oldFileName: line.slice(4),
34863
+ newFileName: nextLine.slice(4)
34864
+ };
34865
+ }
34866
+ }
34867
+ return null;
34868
+ });
34869
+ }
34870
+ function selectLosslessFileName(rawFileName, parsedFileName) {
34871
+ return rawFileName === void 0 || rawFileName.startsWith('"') ? parsedFileName : rawFileName;
34872
+ }
34873
+ function normalizeDiffPath(value) {
34874
+ if (value === void 0 || value === "/dev/null") return null;
34875
+ return value.startsWith("a/") || value.startsWith("b/") ? value.slice(2) : value;
34876
+ }
34877
+ function fitReportedAgentFileChangeReport(report) {
34878
+ const paths = [...report.paths];
34879
+ let truncated = report.truncated;
34880
+ let fitted = report;
34881
+ while (Buffer.byteLength(JSON.stringify(fitted), "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
34882
+ if (paths.length === 0) {
34883
+ throw new AgentFileChangeReportError("invalidOutput", "The audit report exceeds the wire limit");
34884
+ }
34885
+ paths.pop();
34886
+ truncated = true;
34887
+ fitted = {
34888
+ ...report,
34889
+ paths: [...paths],
34890
+ declaredComplete: false,
34891
+ truncated
34892
+ };
34893
+ }
34894
+ return fitted;
34895
+ }
34896
+ function normalizeFileChangeReport(report, workspace) {
34897
+ const lexicalCwd = parseWorkspaceRoot(workspace.cwd);
34898
+ if (lexicalCwd === null) {
34899
+ throw new AgentFileChangeReportError("providerError", "The session working directory is not absolute");
34900
+ }
34901
+ const cwd = canonicalizeWorkspaceRoot(lexicalCwd);
34902
+ const diffRoot = parseWorkspaceRoot(workspace.diffRoot);
34903
+ if (diffRoot === null || diffRoot.flavor !== cwd.flavor) {
34904
+ throw new AgentFileChangeReportError("providerError", "The captured turn-diff root is invalid");
34905
+ }
34906
+ const roots = [cwd, ...workspace.additionalDirectories.flatMap((directory) => {
34907
+ const root = normalizeWorkspaceRoot(directory);
34908
+ return root === null || root.flavor !== cwd.flavor ? [] : [root];
34909
+ })];
34910
+ const paths = [];
34911
+ const seen = /* @__PURE__ */ new Set();
34912
+ let totalBytes = 0;
34913
+ let truncated = false;
34914
+ for (const reportedPath of report.paths) {
34915
+ if (reportedPath.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
34916
+ truncated = true;
34917
+ continue;
34918
+ }
34919
+ const normalized = normalizeReportedPath(reportedPath, diffRoot, roots);
34920
+ if (normalized === null || normalized.value.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
34921
+ truncated = true;
34922
+ continue;
34923
+ }
34924
+ const key = normalized.flavor === "windows" ? normalized.value.toLowerCase() : normalized.value;
34925
+ if (seen.has(key)) {
34926
+ continue;
34927
+ }
34928
+ const bytes = Buffer.byteLength(normalized.value, "utf8");
34929
+ if (paths.length >= AGENT_FILE_CHANGE_REPORT_MAX_PATHS || totalBytes + bytes > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
34930
+ truncated = true;
34931
+ continue;
34932
+ }
34933
+ seen.add(key);
34934
+ paths.push(normalized.value);
34935
+ totalBytes += bytes;
34936
+ }
34937
+ return {
34938
+ paths,
34939
+ declaredComplete: report.complete && !truncated,
34940
+ truncated,
34941
+ ...report.uncertainty ? { uncertainty: report.uncertainty } : {}
34942
+ };
34943
+ }
34944
+ function normalizeWorkspaceRoot(value) {
34945
+ const root = parseWorkspaceRoot(value);
34946
+ return root === null ? null : canonicalizeWorkspaceRoot(root);
34947
+ }
34948
+ function parseWorkspaceRoot(value) {
34949
+ const trimmed = value.trim();
34950
+ if (!isValidPathText(trimmed)) {
34951
+ return null;
34952
+ }
34953
+ if (isWindowsAbsolutePath(trimmed)) {
34954
+ return {
34955
+ value: path5.win32.normalize(trimmed.replace(/\//g, "\\")),
34956
+ flavor: "windows"
34957
+ };
34958
+ }
34959
+ if (path5.posix.isAbsolute(trimmed)) {
34960
+ return {
34961
+ value: path5.posix.normalize(trimmed.replace(/\\/g, "/")),
34962
+ flavor: "posix"
34963
+ };
34964
+ }
34965
+ return null;
34966
+ }
34967
+ function normalizeReportedPath(value, relativeRoot, roots) {
34968
+ 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)) {
34969
+ return null;
34970
+ }
34971
+ let candidate;
34972
+ if (isWindowsAbsolutePath(value)) {
34973
+ candidate = { value: path5.win32.normalize(value.replace(/\//g, "\\")), flavor: "windows" };
34974
+ } else if (path5.posix.isAbsolute(value)) {
34975
+ candidate = { value: path5.posix.normalize(value.replace(/\\/g, "/")), flavor: "posix" };
34976
+ } else if (relativeRoot.flavor === "windows") {
34977
+ candidate = {
34978
+ value: path5.win32.resolve(relativeRoot.value, value.replace(/\//g, "\\")),
34979
+ flavor: "windows"
34980
+ };
34981
+ } else {
34982
+ candidate = {
34983
+ value: path5.posix.resolve(relativeRoot.value, value.replace(/\\/g, "/")),
34984
+ flavor: "posix"
34985
+ };
34986
+ }
34987
+ candidate = canonicalizeReportedPath(candidate);
34988
+ return roots.some((root) => pathIsStrictlyInside(root, candidate)) ? candidate : null;
34989
+ }
34990
+ function findDiffDisplayRoot(cwd) {
34991
+ if (!isNativePathFlavor(cwd.flavor)) return cwd;
34992
+ const pathImplementation = cwd.flavor === "windows" ? path5.win32 : path5.posix;
34993
+ let current = cwd.value;
34994
+ while (true) {
34995
+ if (fs2.existsSync(pathImplementation.join(current, ".git"))) {
34996
+ return canonicalizeWorkspaceRoot({ value: current, flavor: cwd.flavor });
34997
+ }
34998
+ const parent = pathImplementation.dirname(current);
34999
+ if (parent === current) return cwd;
35000
+ current = parent;
35001
+ }
35002
+ }
35003
+ function canonicalizeWorkspaceRoot(root) {
35004
+ if (!isNativePathFlavor(root.flavor)) {
35005
+ return root;
35006
+ }
35007
+ return { ...root, value: canonicalizeFromExistingAncestor(root.value) };
35008
+ }
35009
+ function canonicalizeReportedPath(candidate) {
35010
+ if (!isNativePathFlavor(candidate.flavor)) {
35011
+ return candidate;
35012
+ }
35013
+ const parent = canonicalizeFromExistingAncestor(path5.dirname(candidate.value));
35014
+ return { ...candidate, value: path5.resolve(parent, path5.basename(candidate.value)) };
35015
+ }
35016
+ function canonicalizeFromExistingAncestor(value) {
35017
+ const original = path5.resolve(value);
35018
+ let current = original;
35019
+ const missingSegments = [];
35020
+ while (true) {
35021
+ try {
35022
+ const canonical = fs2.realpathSync.native(current);
35023
+ return path5.resolve(canonical, ...missingSegments.reverse());
35024
+ } catch (error62) {
35025
+ if (!isMissingPathError(error62)) return original;
35026
+ }
35027
+ const parent = path5.dirname(current);
35028
+ if (parent === current) return original;
35029
+ missingSegments.push(path5.basename(current));
35030
+ current = parent;
35031
+ }
35032
+ }
35033
+ function isMissingPathError(error62) {
35034
+ if (typeof error62 !== "object" || error62 === null || !("code" in error62)) return false;
35035
+ return error62.code === "ENOENT" || error62.code === "ENOTDIR";
35036
+ }
35037
+ function isNativePathFlavor(flavor) {
35038
+ return process.platform === "win32" ? flavor === "windows" : flavor === "posix";
35039
+ }
35040
+ function pathIsStrictlyInside(root, candidate) {
35041
+ if (root.flavor !== candidate.flavor) {
35042
+ return false;
35043
+ }
35044
+ const pathImplementation = root.flavor === "windows" ? path5.win32 : path5.posix;
35045
+ const relative = pathImplementation.relative(root.value, candidate.value);
35046
+ return relative.length > 0 && !pathImplementation.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${pathImplementation.sep}`);
35047
+ }
35048
+ function isWindowsAbsolutePath(value) {
35049
+ const portable = value.replace(/\\/g, "/");
35050
+ return /^[A-Za-z]:\//.test(portable) || /^\/\/[^/]+\/[^/]+(?:\/|$)/.test(portable);
35051
+ }
35052
+ function isValidPathText(value) {
35053
+ return value.length > 0 && !/[\u0000-\u001F\u007F-\u009F]/.test(value);
35054
+ }
35055
+ function asRecord2(value) {
35056
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
35057
+ }
35058
+ function hasOnlyKeys(value, allowed) {
35059
+ const allowedKeys = new Set(allowed);
35060
+ return Object.keys(value).every((key) => allowedKeys.has(key));
35061
+ }
35062
+
34725
35063
  // src/tool-calls/ClientCapabilities.ts
34726
35064
  var ClientCapabilities = class _ClientCapabilities {
34727
35065
  static DEFAULT = new _ClientCapabilities({
@@ -34735,6 +35073,7 @@ var ClientCapabilities = class _ClientCapabilities {
34735
35073
  air: { rawInputRendering: false, planContentDelta: false, diffPatch: false },
34736
35074
  diffPatchFormat: "none",
34737
35075
  sessionFailureFormat: "none",
35076
+ agentFileChangeReportFormat: "none",
34738
35077
  permissionPromptFields: false
34739
35078
  });
34740
35079
  /** The client declares `_meta.jetbrains.air`. */
@@ -34754,6 +35093,7 @@ var ClientCapabilities = class _ClientCapabilities {
34754
35093
  air;
34755
35094
  diffPatchFormat;
34756
35095
  sessionFailureFormat;
35096
+ agentFileChangeReportFormat;
34757
35097
  /** A permission request has its own `title` and `description` (ACP v2). */
34758
35098
  permissionPromptFields;
34759
35099
  constructor(values) {
@@ -34767,6 +35107,7 @@ var ClientCapabilities = class _ClientCapabilities {
34767
35107
  this.air = values.air;
34768
35108
  this.diffPatchFormat = values.diffPatchFormat;
34769
35109
  this.sessionFailureFormat = values.sessionFailureFormat;
35110
+ this.agentFileChangeReportFormat = values.agentFileChangeReportFormat;
34770
35111
  this.permissionPromptFields = values.permissionPromptFields;
34771
35112
  }
34772
35113
  static from(capabilities) {
@@ -34790,6 +35131,8 @@ var ClientCapabilities = class _ClientCapabilities {
34790
35131
  diffPatchFormat: clientRequestsNeutralDiffPatch(capabilities) ? "neutral" : diffPatch ? "air" : "none",
34791
35132
  // Likewise, and the client-neutral form selects the whole typed failure lane.
34792
35133
  sessionFailureFormat: clientRequestsNeutralSessionFailure(capabilities) ? "neutral" : clientSupportsAirCapability(capabilities, AIR_SESSION_FAILURE_KEY) ? "air" : "none",
35134
+ // Likewise. The request and the report use the selected form.
35135
+ agentFileChangeReportFormat: clientRequestsNeutralAgentFileChangeReport(capabilities) ? "neutral" : clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY) ? "air" : "none",
34793
35136
  permissionPromptFields: false
34794
35137
  });
34795
35138
  }
@@ -34814,6 +35157,8 @@ var ClientCapabilities = class _ClientCapabilities {
34814
35157
  diffPatchFormat: "acpV2",
34815
35158
  // ACP v2 has its own terminal failure state, so it ignores the client-neutral opt-in.
34816
35159
  sessionFailureFormat: clientSupportsAirCapability(capabilities, AIR_SESSION_FAILURE_KEY) ? "air" : "none",
35160
+ // The client-neutral report is an ACP v1 extension, so v2 ignores its opt-in.
35161
+ agentFileChangeReportFormat: clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY) ? "air" : "none",
34817
35162
  permissionPromptFields: true
34818
35163
  });
34819
35164
  }
@@ -36479,418 +36824,119 @@ var StandardSubagentEventRouter = class {
36479
36824
  await child.foreground.update({ state: "idle" });
36480
36825
  } else if (thread.status.type === "active" && thread.status.activeFlags.length === 0) {
36481
36826
  child.turnId ??= turnId ?? null;
36482
- if (child.turnId !== null) this.beginForegroundTurn(child, child.turnId);
36483
- await child.foreground.start();
36484
- }
36485
- await this.publishCancellation(child);
36486
- }
36487
- /** Historical state bypasses the current foreground cache and grants no runtime ownership. */
36488
- async replayTurnOutcome(threadId, turn) {
36489
- const child = this.children.get(threadId);
36490
- const state = turnEndState(turn);
36491
- if (!child || state === void 0 || this.retired) return;
36492
- await this.ensureAnnounced(child);
36493
- if (this.retired) return;
36494
- await this.session.updateSubagentState(child.sessionId, child.parentSessionId, state);
36495
- }
36496
- childSessionIds() {
36497
- return [...this.children.values()].map((child) => child.sessionId);
36498
- }
36499
- isNativeSubagentThread(threadId) {
36500
- return this.children.has(threadId);
36501
- }
36502
- shouldIgnore() {
36503
- return false;
36504
- }
36505
- notificationSessionId(notification) {
36506
- const threadId = notification.params.threadId;
36507
- return typeof threadId === "string" ? this.children.get(threadId)?.sessionId ?? this.rootSessionId : this.rootSessionId;
36508
- }
36509
- takeBufferedNotifications() {
36510
- return this.replayQueue.splice(0);
36511
- }
36512
- async waitForMaterializedSession(threadId) {
36513
- if (this.retired) return null;
36514
- await this.materializePending();
36515
- const child = this.children.get(threadId);
36516
- if (child) await this.ensureAnnounced(child);
36517
- return child?.sessionId ?? null;
36518
- }
36519
- closingChildSessions(notification) {
36520
- if (notification.method !== "turn/completed") return [];
36521
- const child = this.children.get(notification.params.threadId);
36522
- const turn = notification.params.turn;
36523
- if (!child || turn.status === "inProgress" || child.endedTurns.has(turn.id) || child.turnId !== null && child.turnId !== turn.id) return [];
36524
- return [{
36525
- threadId: child.threadId,
36526
- sessionId: child.sessionId,
36527
- state: turn.status === "interrupted" ? "cancelled" : turn.status === "failed" ? "failed" : "completed"
36528
- }];
36529
- }
36530
- async wait(_signal) {
36531
- return "settled";
36532
- }
36533
- hasOutstanding() {
36534
- return [...this.children.values()].some((child) => child.turnId !== null);
36535
- }
36536
- legacyActivityStarted(item) {
36537
- this.legacyActivities.add(item.id);
36538
- return SubagentActivityReporter.activity(item, "in_progress", "start");
36539
- }
36540
- legacyActivityCompleted(item) {
36541
- return SubagentActivityReporter.activity(item, "completed", this.legacyActivities.delete(item.id) ? "update" : "start");
36542
- }
36543
- legacyCollaborationStarted(item) {
36544
- return CollabAgentReporter.started(item);
36545
- }
36546
- legacyCollaborationCompleted(item) {
36547
- return CollabAgentReporter.completed(item);
36548
- }
36549
- };
36550
- function turnEndState(turn) {
36551
- switch (turn.status) {
36552
- case "inProgress":
36553
- return void 0;
36554
- case "completed":
36555
- return toV2IdleState({ stopReason: "end_turn" });
36556
- case "interrupted":
36557
- return toV2IdleState({ stopReason: "cancelled" });
36558
- case "failed":
36559
- return toV2IdleState({ stopReason: "end_turn" }, {
36560
- code: -32603,
36561
- message: turn.error ? readableServiceErrorMessage(turn.error.message) : "Subagent work failed"
36562
- });
36563
- }
36564
- }
36565
-
36566
- // src/RateLimitsMap.ts
36567
- function rateLimitId(snapshot, fallback = "codex") {
36568
- return snapshot.limitId ?? fallback;
36569
- }
36570
- function createRateLimitsMap(response) {
36571
- const result = /* @__PURE__ */ new Map();
36572
- const snapshots = Object.entries(response.rateLimitsByLimitId ?? {}).filter((entry) => entry[1] !== void 0);
36573
- if (snapshots.length === 0) {
36574
- snapshots.push([rateLimitId(response.rateLimits), response.rateLimits]);
36575
- }
36576
- for (const [fallbackId, snapshot] of snapshots) {
36577
- const limitId = rateLimitId(snapshot, fallbackId);
36578
- result.set(limitId, {
36579
- limitId,
36580
- limitName: snapshot.limitName ?? limitId,
36581
- snapshot
36582
- });
36583
- }
36584
- return result;
36585
- }
36586
- function mergeRateLimitSnapshot(previous, update) {
36587
- return {
36588
- ...update,
36589
- limitId: update.limitId ?? "codex",
36590
- credits: update.credits ?? previous.credits,
36591
- individualLimit: update.individualLimit ?? previous.individualLimit,
36592
- spendControlReached: update.spendControlReached ?? previous.spendControlReached,
36593
- planType: update.planType ?? previous.planType
36594
- };
36595
- }
36596
-
36597
- // src/AgentFileChangeReport.ts
36598
- import fs2 from "node:fs";
36599
- import path5 from "node:path";
36600
- var AGENT_FILE_CHANGE_REPORT_VERSION = 1;
36601
- var AGENT_FILE_CHANGE_REPORT_MAX_PATHS = 1024;
36602
- var AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH = 4096;
36603
- var AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES = 256 * 1024;
36604
- var AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES = 8 * 1024 * 1024;
36605
- 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.";
36606
- function captureAgentFileChangeWorkspace(cwd, additionalDirectories) {
36607
- const lexicalCwd = parseWorkspaceRoot(cwd);
36608
- return {
36609
- cwd,
36610
- additionalDirectories: [...additionalDirectories],
36611
- diffRoot: lexicalCwd === null ? cwd : findDiffDisplayRoot(lexicalCwd).value
36612
- };
36613
- }
36614
- function parseAgentFileChangeReportRequest(meta3) {
36615
- const jetbrains = asRecord2(meta3?.[JETBRAINS_META_KEY]);
36616
- const air = asRecord2(jetbrains?.[AIR_META_KEY]);
36617
- const request = asRecord2(air?.[AIR_AGENT_FILE_CHANGE_REPORT_REQUEST_KEY]);
36618
- if (request === null || !hasOnlyKeys(request, ["version", "requestId"]) || request["version"] !== AGENT_FILE_CHANGE_REPORT_VERSION) {
36619
- return null;
36620
- }
36621
- const requestId = request["requestId"];
36622
- if (typeof requestId !== "string" || !/^[A-Za-z0-9._:-]{1,128}$/.test(requestId)) {
36623
- return null;
36624
- }
36625
- return { version: AGENT_FILE_CHANGE_REPORT_VERSION, requestId };
36626
- }
36627
- function createReportedAgentFileChangeReport(requestId, diff, workspace) {
36628
- if (Buffer.byteLength(diff, "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_DIFF_BYTES) {
36629
- throw new AgentFileChangeReportError("invalidOutput", "The turn diff exceeds the parser input limit");
36630
- }
36631
- const parsedReport = parseTurnDiff(diff);
36632
- const normalized = normalizeFileChangeReport(parsedReport, workspace);
36633
- return fitReportedAgentFileChangeReport({
36634
- version: AGENT_FILE_CHANGE_REPORT_VERSION,
36635
- requestId,
36636
- status: "reported",
36637
- ...normalized
36638
- });
36639
- }
36640
- function createUnavailableAgentFileChangeReport(requestId, reason) {
36641
- return {
36642
- version: AGENT_FILE_CHANGE_REPORT_VERSION,
36643
- requestId,
36644
- status: "unavailable",
36645
- reason
36646
- };
36647
- }
36648
- var AgentFileChangeReportError = class extends Error {
36649
- reason;
36650
- constructor(reason, message) {
36651
- super(message);
36652
- this.name = "AgentFileChangeReportError";
36653
- this.reason = reason;
36654
- }
36655
- };
36656
- function parseTurnDiff(diff) {
36657
- if (diff.trim() === "") {
36658
- return { paths: [], complete: false, uncertainty: TURN_DIFF_UNCERTAINTY };
36659
- }
36660
- let patches;
36661
- try {
36662
- patches = parsePatch(diff);
36663
- } catch (error62) {
36664
- throw new AgentFileChangeReportError(
36665
- "invalidOutput",
36666
- `The turn diff is not valid unified diff: ${error62 instanceof Error ? error62.message : String(error62)}`
36667
- );
36668
- }
36669
- if (patches.length === 0) {
36670
- throw new AgentFileChangeReportError("invalidOutput", "The turn diff contains no parseable file patches");
36671
- }
36672
- const rawFileHeaders = extractRawFileHeaders(diff);
36673
- const paths = [];
36674
- for (const [index, patch] of patches.entries()) {
36675
- const rawHeaders = rawFileHeaders[index];
36676
- const oldPath = normalizeDiffPath(selectLosslessFileName(rawHeaders?.oldFileName, patch.oldFileName));
36677
- const newPath = normalizeDiffPath(selectLosslessFileName(rawHeaders?.newFileName, patch.newFileName));
36678
- if (oldPath === null && newPath === null) {
36679
- throw new AgentFileChangeReportError("invalidOutput", "The turn diff contains a patch without a file path");
36680
- }
36681
- if (oldPath !== null) paths.push(oldPath);
36682
- if (newPath !== null) paths.push(newPath);
36683
- }
36684
- return { paths, complete: false, uncertainty: TURN_DIFF_UNCERTAINTY };
36685
- }
36686
- function extractRawFileHeaders(diff) {
36687
- return diff.split(/(?=^diff --git )/m).filter((section) => section.trim() !== "").map((section) => {
36688
- const lines = section.split(/\r?\n/);
36689
- for (let index = 0; index < lines.length; index += 1) {
36690
- const line = lines[index];
36691
- if (line?.startsWith("@@ ")) return null;
36692
- const nextLine = lines[index + 1];
36693
- if (line?.startsWith("--- ") && nextLine?.startsWith("+++ ")) {
36694
- return {
36695
- oldFileName: line.slice(4),
36696
- newFileName: nextLine.slice(4)
36697
- };
36698
- }
36699
- }
36700
- return null;
36701
- });
36702
- }
36703
- function selectLosslessFileName(rawFileName, parsedFileName) {
36704
- return rawFileName === void 0 || rawFileName.startsWith('"') ? parsedFileName : rawFileName;
36705
- }
36706
- function normalizeDiffPath(value) {
36707
- if (value === void 0 || value === "/dev/null") return null;
36708
- return value.startsWith("a/") || value.startsWith("b/") ? value.slice(2) : value;
36709
- }
36710
- function fitReportedAgentFileChangeReport(report) {
36711
- const paths = [...report.paths];
36712
- let truncated = report.truncated;
36713
- let fitted = report;
36714
- while (Buffer.byteLength(JSON.stringify(fitted), "utf8") > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
36715
- if (paths.length === 0) {
36716
- throw new AgentFileChangeReportError("invalidOutput", "The audit report exceeds the wire limit");
36717
- }
36718
- paths.pop();
36719
- truncated = true;
36720
- fitted = {
36721
- ...report,
36722
- paths: [...paths],
36723
- declaredComplete: false,
36724
- truncated
36725
- };
36827
+ if (child.turnId !== null) this.beginForegroundTurn(child, child.turnId);
36828
+ await child.foreground.start();
36829
+ }
36830
+ await this.publishCancellation(child);
36726
36831
  }
36727
- return fitted;
36728
- }
36729
- function normalizeFileChangeReport(report, workspace) {
36730
- const lexicalCwd = parseWorkspaceRoot(workspace.cwd);
36731
- if (lexicalCwd === null) {
36732
- throw new AgentFileChangeReportError("providerError", "The session working directory is not absolute");
36832
+ /** Historical state bypasses the current foreground cache and grants no runtime ownership. */
36833
+ async replayTurnOutcome(threadId, turn) {
36834
+ const child = this.children.get(threadId);
36835
+ const state = turnEndState(turn);
36836
+ if (!child || state === void 0 || this.retired) return;
36837
+ await this.ensureAnnounced(child);
36838
+ if (this.retired) return;
36839
+ await this.session.updateSubagentState(child.sessionId, child.parentSessionId, state);
36733
36840
  }
36734
- const cwd = canonicalizeWorkspaceRoot(lexicalCwd);
36735
- const diffRoot = parseWorkspaceRoot(workspace.diffRoot);
36736
- if (diffRoot === null || diffRoot.flavor !== cwd.flavor) {
36737
- throw new AgentFileChangeReportError("providerError", "The captured turn-diff root is invalid");
36841
+ childSessionIds() {
36842
+ return [...this.children.values()].map((child) => child.sessionId);
36738
36843
  }
36739
- const roots = [cwd, ...workspace.additionalDirectories.flatMap((directory) => {
36740
- const root = normalizeWorkspaceRoot(directory);
36741
- return root === null || root.flavor !== cwd.flavor ? [] : [root];
36742
- })];
36743
- const paths = [];
36744
- const seen = /* @__PURE__ */ new Set();
36745
- let totalBytes = 0;
36746
- let truncated = false;
36747
- for (const reportedPath of report.paths) {
36748
- if (reportedPath.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
36749
- truncated = true;
36750
- continue;
36751
- }
36752
- const normalized = normalizeReportedPath(reportedPath, diffRoot, roots);
36753
- if (normalized === null || normalized.value.length > AGENT_FILE_CHANGE_REPORT_MAX_PATH_LENGTH) {
36754
- truncated = true;
36755
- continue;
36756
- }
36757
- const key = normalized.flavor === "windows" ? normalized.value.toLowerCase() : normalized.value;
36758
- if (seen.has(key)) {
36759
- continue;
36760
- }
36761
- const bytes = Buffer.byteLength(normalized.value, "utf8");
36762
- if (paths.length >= AGENT_FILE_CHANGE_REPORT_MAX_PATHS || totalBytes + bytes > AGENT_FILE_CHANGE_REPORT_MAX_TOTAL_BYTES) {
36763
- truncated = true;
36764
- continue;
36765
- }
36766
- seen.add(key);
36767
- paths.push(normalized.value);
36768
- totalBytes += bytes;
36844
+ isNativeSubagentThread(threadId) {
36845
+ return this.children.has(threadId);
36769
36846
  }
36770
- return {
36771
- paths,
36772
- declaredComplete: report.complete && !truncated,
36773
- truncated,
36774
- ...report.uncertainty ? { uncertainty: report.uncertainty } : {}
36775
- };
36776
- }
36777
- function normalizeWorkspaceRoot(value) {
36778
- const root = parseWorkspaceRoot(value);
36779
- return root === null ? null : canonicalizeWorkspaceRoot(root);
36780
- }
36781
- function parseWorkspaceRoot(value) {
36782
- const trimmed = value.trim();
36783
- if (!isValidPathText(trimmed)) {
36784
- return null;
36847
+ shouldIgnore() {
36848
+ return false;
36785
36849
  }
36786
- if (isWindowsAbsolutePath(trimmed)) {
36787
- return {
36788
- value: path5.win32.normalize(trimmed.replace(/\//g, "\\")),
36789
- flavor: "windows"
36790
- };
36850
+ notificationSessionId(notification) {
36851
+ const threadId = notification.params.threadId;
36852
+ return typeof threadId === "string" ? this.children.get(threadId)?.sessionId ?? this.rootSessionId : this.rootSessionId;
36791
36853
  }
36792
- if (path5.posix.isAbsolute(trimmed)) {
36793
- return {
36794
- value: path5.posix.normalize(trimmed.replace(/\\/g, "/")),
36795
- flavor: "posix"
36796
- };
36854
+ takeBufferedNotifications() {
36855
+ return this.replayQueue.splice(0);
36797
36856
  }
36798
- return null;
36799
- }
36800
- function normalizeReportedPath(value, relativeRoot, roots) {
36801
- 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)) {
36802
- return null;
36857
+ async waitForMaterializedSession(threadId) {
36858
+ if (this.retired) return null;
36859
+ await this.materializePending();
36860
+ const child = this.children.get(threadId);
36861
+ if (child) await this.ensureAnnounced(child);
36862
+ return child?.sessionId ?? null;
36803
36863
  }
36804
- let candidate;
36805
- if (isWindowsAbsolutePath(value)) {
36806
- candidate = { value: path5.win32.normalize(value.replace(/\//g, "\\")), flavor: "windows" };
36807
- } else if (path5.posix.isAbsolute(value)) {
36808
- candidate = { value: path5.posix.normalize(value.replace(/\\/g, "/")), flavor: "posix" };
36809
- } else if (relativeRoot.flavor === "windows") {
36810
- candidate = {
36811
- value: path5.win32.resolve(relativeRoot.value, value.replace(/\//g, "\\")),
36812
- flavor: "windows"
36813
- };
36814
- } else {
36815
- candidate = {
36816
- value: path5.posix.resolve(relativeRoot.value, value.replace(/\\/g, "/")),
36817
- flavor: "posix"
36818
- };
36864
+ closingChildSessions(notification) {
36865
+ if (notification.method !== "turn/completed") return [];
36866
+ const child = this.children.get(notification.params.threadId);
36867
+ const turn = notification.params.turn;
36868
+ if (!child || turn.status === "inProgress" || child.endedTurns.has(turn.id) || child.turnId !== null && child.turnId !== turn.id) return [];
36869
+ return [{
36870
+ threadId: child.threadId,
36871
+ sessionId: child.sessionId,
36872
+ state: turn.status === "interrupted" ? "cancelled" : turn.status === "failed" ? "failed" : "completed"
36873
+ }];
36819
36874
  }
36820
- candidate = canonicalizeReportedPath(candidate);
36821
- return roots.some((root) => pathIsStrictlyInside(root, candidate)) ? candidate : null;
36822
- }
36823
- function findDiffDisplayRoot(cwd) {
36824
- if (!isNativePathFlavor(cwd.flavor)) return cwd;
36825
- const pathImplementation = cwd.flavor === "windows" ? path5.win32 : path5.posix;
36826
- let current = cwd.value;
36827
- while (true) {
36828
- if (fs2.existsSync(pathImplementation.join(current, ".git"))) {
36829
- return canonicalizeWorkspaceRoot({ value: current, flavor: cwd.flavor });
36830
- }
36831
- const parent = pathImplementation.dirname(current);
36832
- if (parent === current) return cwd;
36833
- current = parent;
36875
+ async wait(_signal) {
36876
+ return "settled";
36834
36877
  }
36835
- }
36836
- function canonicalizeWorkspaceRoot(root) {
36837
- if (!isNativePathFlavor(root.flavor)) {
36838
- return root;
36878
+ hasOutstanding() {
36879
+ return [...this.children.values()].some((child) => child.turnId !== null);
36839
36880
  }
36840
- return { ...root, value: canonicalizeFromExistingAncestor(root.value) };
36841
- }
36842
- function canonicalizeReportedPath(candidate) {
36843
- if (!isNativePathFlavor(candidate.flavor)) {
36844
- return candidate;
36881
+ legacyActivityStarted(item) {
36882
+ this.legacyActivities.add(item.id);
36883
+ return SubagentActivityReporter.activity(item, "in_progress", "start");
36845
36884
  }
36846
- const parent = canonicalizeFromExistingAncestor(path5.dirname(candidate.value));
36847
- return { ...candidate, value: path5.resolve(parent, path5.basename(candidate.value)) };
36848
- }
36849
- function canonicalizeFromExistingAncestor(value) {
36850
- const original = path5.resolve(value);
36851
- let current = original;
36852
- const missingSegments = [];
36853
- while (true) {
36854
- try {
36855
- const canonical = fs2.realpathSync.native(current);
36856
- return path5.resolve(canonical, ...missingSegments.reverse());
36857
- } catch (error62) {
36858
- if (!isMissingPathError(error62)) return original;
36859
- }
36860
- const parent = path5.dirname(current);
36861
- if (parent === current) return original;
36862
- missingSegments.push(path5.basename(current));
36863
- current = parent;
36885
+ legacyActivityCompleted(item) {
36886
+ return SubagentActivityReporter.activity(item, "completed", this.legacyActivities.delete(item.id) ? "update" : "start");
36864
36887
  }
36865
- }
36866
- function isMissingPathError(error62) {
36867
- if (typeof error62 !== "object" || error62 === null || !("code" in error62)) return false;
36868
- return error62.code === "ENOENT" || error62.code === "ENOTDIR";
36869
- }
36870
- function isNativePathFlavor(flavor) {
36871
- return process.platform === "win32" ? flavor === "windows" : flavor === "posix";
36872
- }
36873
- function pathIsStrictlyInside(root, candidate) {
36874
- if (root.flavor !== candidate.flavor) {
36875
- return false;
36888
+ legacyCollaborationStarted(item) {
36889
+ return CollabAgentReporter.started(item);
36890
+ }
36891
+ legacyCollaborationCompleted(item) {
36892
+ return CollabAgentReporter.completed(item);
36893
+ }
36894
+ };
36895
+ function turnEndState(turn) {
36896
+ switch (turn.status) {
36897
+ case "inProgress":
36898
+ return void 0;
36899
+ case "completed":
36900
+ return toV2IdleState({ stopReason: "end_turn" });
36901
+ case "interrupted":
36902
+ return toV2IdleState({ stopReason: "cancelled" });
36903
+ case "failed":
36904
+ return toV2IdleState({ stopReason: "end_turn" }, {
36905
+ code: -32603,
36906
+ message: turn.error ? readableServiceErrorMessage(turn.error.message) : "Subagent work failed"
36907
+ });
36876
36908
  }
36877
- const pathImplementation = root.flavor === "windows" ? path5.win32 : path5.posix;
36878
- const relative = pathImplementation.relative(root.value, candidate.value);
36879
- return relative.length > 0 && !pathImplementation.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${pathImplementation.sep}`);
36880
- }
36881
- function isWindowsAbsolutePath(value) {
36882
- const portable = value.replace(/\\/g, "/");
36883
- return /^[A-Za-z]:\//.test(portable) || /^\/\/[^/]+\/[^/]+(?:\/|$)/.test(portable);
36884
36909
  }
36885
- function isValidPathText(value) {
36886
- return value.length > 0 && !/[\u0000-\u001F\u007F-\u009F]/.test(value);
36910
+
36911
+ // src/RateLimitsMap.ts
36912
+ function rateLimitId(snapshot, fallback = "codex") {
36913
+ return snapshot.limitId ?? fallback;
36887
36914
  }
36888
- function asRecord2(value) {
36889
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
36915
+ function createRateLimitsMap(response) {
36916
+ const result = /* @__PURE__ */ new Map();
36917
+ const snapshots = Object.entries(response.rateLimitsByLimitId ?? {}).filter((entry) => entry[1] !== void 0);
36918
+ if (snapshots.length === 0) {
36919
+ snapshots.push([rateLimitId(response.rateLimits), response.rateLimits]);
36920
+ }
36921
+ for (const [fallbackId, snapshot] of snapshots) {
36922
+ const limitId = rateLimitId(snapshot, fallbackId);
36923
+ result.set(limitId, {
36924
+ limitId,
36925
+ limitName: snapshot.limitName ?? limitId,
36926
+ snapshot
36927
+ });
36928
+ }
36929
+ return result;
36890
36930
  }
36891
- function hasOnlyKeys(value, allowed) {
36892
- const allowedKeys = new Set(allowed);
36893
- return Object.keys(value).every((key) => allowedKeys.has(key));
36931
+ function mergeRateLimitSnapshot(previous, update) {
36932
+ return {
36933
+ ...update,
36934
+ limitId: update.limitId ?? "codex",
36935
+ credits: update.credits ?? previous.credits,
36936
+ individualLimit: update.individualLimit ?? previous.individualLimit,
36937
+ spendControlReached: update.spendControlReached ?? previous.spendControlReached,
36938
+ planType: update.planType ?? previous.planType
36939
+ };
36894
36940
  }
36895
36941
 
36896
36942
  // src/SessionNotice.ts
@@ -40675,7 +40721,7 @@ var package_default = {
40675
40721
  publishConfig: {
40676
40722
  access: "public"
40677
40723
  },
40678
- version: "2.5.0-alas.5",
40724
+ version: "2.5.0-alas.6",
40679
40725
  description: "",
40680
40726
  main: "dist/index.js",
40681
40727
  bin: {
@@ -40753,7 +40799,7 @@ var package_default = {
40753
40799
  alasDownstream: {
40754
40800
  upstreamVersion: "2.5.0",
40755
40801
  upstreamCommit: "34e08970aa324a2be985f5080674d5aa91d7666f",
40756
- sourceCommit: "d1c53266b4d5d1f308323259b81d01ea687104ef"
40802
+ sourceCommit: "7c99c083270255f2960fa4cd2da93f72bdf402ad"
40757
40803
  }
40758
40804
  };
40759
40805
 
@@ -52176,9 +52222,6 @@ var DENY_ALL_ELICITATIONS = {
52176
52222
  handleElicitation: async () => ({ action: "cancel", content: null, _meta: null }),
52177
52223
  handleUserInput: async () => ({ answers: {} })
52178
52224
  };
52179
- function clientSupportsAgentFileChangeReports(capabilities) {
52180
- return clientSupportsAirCapability(capabilities, AIR_AGENT_FILE_CHANGE_REPORT_KEY);
52181
- }
52182
52225
  function isAuthRequiredError(error62) {
52183
52226
  return error62 instanceof RequestError && error62.code === RequestError.authRequired().code;
52184
52227
  }
@@ -52625,6 +52668,11 @@ var CodexAcpServer = class {
52625
52668
  ...protocolVersion === 1 && this.capabilities.sessionFailureFormat === "neutral" ? {
52626
52669
  [NEUTRAL_SESSION_FAILURE_META_KEY]: neutralSessionFailureCapability()
52627
52670
  } : {},
52671
+ // The client-neutral agent file-change report, see `docs/air-extensions.md`. It is an ACP v1 extension,
52672
+ // so `ClientCapabilities.fromV2` never selects it.
52673
+ ...protocolVersion === 1 && this.capabilities.agentFileChangeReportFormat === "neutral" ? {
52674
+ [NEUTRAL_AGENT_FILE_CHANGE_REPORT_META_KEY]: neutralAgentFileChangeReportCapability()
52675
+ } : {},
52628
52676
  // The session index for a client that opted in without AIR, see `docs/air-extensions.md`.
52629
52677
  ...neutralSessionIndex ? {
52630
52678
  [NEUTRAL_SESSION_INDEX_META_KEY]: neutralSessionIndex
@@ -55315,7 +55363,7 @@ You have been logged out. Please try again.`);
55315
55363
  title
55316
55364
  });
55317
55365
  }
55318
- async publishAgentFileChangeReport(sessionState, turnId, request, unavailableReason, turnDiff, workspace) {
55366
+ async publishAgentFileChangeReport(sessionState, format, turnId, request, unavailableReason, turnDiff, workspace) {
55319
55367
  let report;
55320
55368
  try {
55321
55369
  report = turnId === null ? createUnavailableAgentFileChangeReport(request.requestId, unavailableReason) : createReportedAgentFileChangeReport(request.requestId, turnDiff, workspace);
@@ -55333,14 +55381,7 @@ You have been logged out. Please try again.`);
55333
55381
  const session = new ACPSessionConnection(this.connection, sessionState.sessionId);
55334
55382
  await session.update({
55335
55383
  sessionUpdate: "session_info_update",
55336
- _meta: {
55337
- [JETBRAINS_META_KEY]: {
55338
- [AIR_META_KEY]: {
55339
- [AIR_EXTENSION_VERSION_KEY]: AIR_EXTENSION_VERSION,
55340
- [AIR_AGENT_FILE_CHANGE_REPORT_KEY]: report
55341
- }
55342
- }
55343
- }
55384
+ _meta: agentFileChangeReportMeta(format, report)
55344
55385
  });
55345
55386
  } catch (error62) {
55346
55387
  logger.error("Failed to publish agent file-change report", error62);
@@ -56013,7 +56054,8 @@ You have been logged out. Please try again.`);
56013
56054
  const sessionState = this.getSessionState(params.sessionId);
56014
56055
  const clearing = sessionState.promptSuggestions?.clear();
56015
56056
  if (clearing) await clearing;
56016
- const agentFileChangeReportRequest = clientSupportsAgentFileChangeReports(this.clientCapabilities) ? parseAgentFileChangeReportRequest(params._meta) : null;
56057
+ const agentFileChangeReportFormat = this.capabilities.agentFileChangeReportFormat;
56058
+ const agentFileChangeReportRequest = agentFileChangeReportRequestFor(agentFileChangeReportFormat, params._meta);
56017
56059
  const agentFileChangeWorkspace = agentFileChangeReportRequest === null ? null : captureAgentFileChangeWorkspace(sessionState.cwd, sessionState.additionalDirectories);
56018
56060
  let agentFileChangeReportTurnId = null;
56019
56061
  let agentFileChangeReportUnavailableReason = "providerError";
@@ -56547,7 +56589,7 @@ You have been logged out. Please try again.`);
56547
56589
  } catch (error62) {
56548
56590
  logger.error("Failed to publish terminal compaction or subagent state during prompt cleanup", error62);
56549
56591
  }
56550
- if (agentFileChangeReportRequest !== null && agentFileChangeWorkspace !== null) {
56592
+ if (agentFileChangeReportFormat !== "none" && agentFileChangeReportRequest !== null && agentFileChangeWorkspace !== null) {
56551
56593
  if (promptWasCancelled || activePrompt.signal.aborted || this.sessionIsClosing(params.sessionId)) {
56552
56594
  agentFileChangeReportTurnId = null;
56553
56595
  agentFileChangeReportUnavailableReason = "cancelled";
@@ -56557,6 +56599,7 @@ You have been logged out. Please try again.`);
56557
56599
  }
56558
56600
  await this.publishAgentFileChangeReport(
56559
56601
  sessionState,
56602
+ agentFileChangeReportFormat,
56560
56603
  agentFileChangeReportTurnId,
56561
56604
  agentFileChangeReportRequest,
56562
56605
  agentFileChangeReportUnavailableReason,
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "2.5.0-alas.5",
6
+ "version": "2.5.0-alas.6",
7
7
  "description": "",
8
8
  "main": "dist/index.js",
9
9
  "bin": {
@@ -81,6 +81,6 @@
81
81
  "alasDownstream": {
82
82
  "upstreamVersion": "2.5.0",
83
83
  "upstreamCommit": "34e08970aa324a2be985f5080674d5aa91d7666f",
84
- "sourceCommit": "d1c53266b4d5d1f308323259b81d01ea687104ef"
84
+ "sourceCommit": "7c99c083270255f2960fa4cd2da93f72bdf402ad"
85
85
  }
86
86
  }