@cydm/pie 1.0.16 → 1.0.18

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.
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createAskUserCapability
4
- } from "../../../chunks/chunk-7GAYJ6AF.js";
4
+ } from "../../../chunks/chunk-G4GV2CRT.js";
5
5
  import "../../../chunks/chunk-VE2HDCNB.js";
6
6
  import "../../../chunks/chunk-5DA2D3K2.js";
7
7
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -7,7 +7,7 @@ import {
7
7
  isPlanModeSafeCommand,
8
8
  markCompletedPlanSteps,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-7GAYJ6AF.js";
10
+ } from "../../../chunks/chunk-G4GV2CRT.js";
11
11
  import "../../../chunks/chunk-VE2HDCNB.js";
12
12
  import "../../../chunks/chunk-5DA2D3K2.js";
13
13
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -1,11 +1,11 @@
1
1
  import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
2
  import {
3
3
  createCliHostCapabilities
4
- } from "../../../chunks/chunk-62XU6P2H.js";
4
+ } from "../../../chunks/chunk-MHFUWY7I.js";
5
5
  import {
6
6
  createSharedFileSystemTools,
7
7
  createSubagentCapability
8
- } from "../../../chunks/chunk-7GAYJ6AF.js";
8
+ } from "../../../chunks/chunk-G4GV2CRT.js";
9
9
  import "../../../chunks/chunk-VE2HDCNB.js";
10
10
  import "../../../chunks/chunk-5DA2D3K2.js";
11
11
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -7,7 +7,7 @@ import {
7
7
  executeManageTodoList,
8
8
  executionStateToTodos,
9
9
  restoreExecutionState
10
- } from "../../../chunks/chunk-7GAYJ6AF.js";
10
+ } from "../../../chunks/chunk-G4GV2CRT.js";
11
11
  import "../../../chunks/chunk-VE2HDCNB.js";
12
12
  import "../../../chunks/chunk-5DA2D3K2.js";
13
13
  import "../../../chunks/chunk-TG2EQLX2.js";
@@ -1633,10 +1633,17 @@ ${sections.join("\n\n")}` : "";
1633
1633
  }
1634
1634
  async function createCompactionSummary(messages, options = {}) {
1635
1635
  const { model, apiKey, systemPrompt, compactPrompt, signal } = options;
1636
+ const throwIfAborted = () => {
1637
+ if (signal?.aborted) {
1638
+ throw new Error("Compaction aborted");
1639
+ }
1640
+ };
1636
1641
  if (!model) {
1642
+ throwIfAborted();
1637
1643
  return appendFileOperationsToSummary(createSimpleSummary(messages), messages);
1638
1644
  }
1639
1645
  try {
1646
+ throwIfAborted();
1640
1647
  const response = await streamSimple(
1641
1648
  model,
1642
1649
  {
@@ -1655,8 +1662,10 @@ async function createCompactionSummary(messages, options = {}) {
1655
1662
  signal
1656
1663
  }
1657
1664
  ).result();
1665
+ throwIfAborted();
1658
1666
  return appendFileOperationsToSummary(getAssistantText(response) || createSimpleSummary(messages), messages);
1659
1667
  } catch (error) {
1668
+ throwIfAborted();
1660
1669
  console.warn("[Compaction] Failed to create Codex-style summary:", error);
1661
1670
  return appendFileOperationsToSummary(createSimpleSummary(messages), messages);
1662
1671
  }
@@ -2970,6 +2979,7 @@ var AgentSessionAutoCompactScheduler = class {
2970
2979
  autoCompactTimer;
2971
2980
  pendingAutoCompact;
2972
2981
  runningAutoCompact;
2982
+ runningAbortController;
2973
2983
  pendingWait;
2974
2984
  resolvePendingWait;
2975
2985
  get hasPendingAutoCompact() {
@@ -3001,11 +3011,17 @@ var AgentSessionAutoCompactScheduler = class {
3001
3011
  this.schedule(pending, 100);
3002
3012
  return;
3003
3013
  }
3004
- this.runningAutoCompact = this.options.runAutoCompact(pending).catch(() => {
3014
+ const abortController = new AbortController();
3015
+ this.runningAbortController = abortController;
3016
+ const running = this.options.runAutoCompact(pending, abortController.signal).catch(() => {
3005
3017
  }).finally(() => {
3006
- this.runningAutoCompact = void 0;
3007
- this.resolvePending();
3018
+ if (this.runningAutoCompact === running) {
3019
+ this.runningAutoCompact = void 0;
3020
+ this.runningAbortController = void 0;
3021
+ this.resolvePending();
3022
+ }
3008
3023
  });
3024
+ this.runningAutoCompact = running;
3009
3025
  }, delayMs);
3010
3026
  }
3011
3027
  cancel() {
@@ -3015,6 +3031,9 @@ var AgentSessionAutoCompactScheduler = class {
3015
3031
  this.autoCompactTimer = void 0;
3016
3032
  }
3017
3033
  this.pendingAutoCompact = void 0;
3034
+ this.runningAbortController?.abort();
3035
+ this.runningAbortController = void 0;
3036
+ this.runningAutoCompact = void 0;
3018
3037
  this.resolvePending();
3019
3038
  }
3020
3039
  ensurePendingWait() {
@@ -3143,8 +3162,15 @@ async function runAgentSessionCompaction(params) {
3143
3162
  if (!params.compaction) {
3144
3163
  throw new Error("No compaction handler configured");
3145
3164
  }
3165
+ const abortedResult = () => ({ aborted: true });
3166
+ const isAborted = () => params.signal?.aborted === true;
3146
3167
  params.emit({ type: "auto_compaction_start", reason: params.reason, willRetry: params.willRetry });
3147
3168
  try {
3169
+ if (isAborted()) {
3170
+ const result2 = abortedResult();
3171
+ params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, result: result2 });
3172
+ return result2;
3173
+ }
3148
3174
  if (params.willRetry) {
3149
3175
  params.removeTrailingAssistantError();
3150
3176
  }
@@ -3154,22 +3180,43 @@ async function runAgentSessionCompaction(params) {
3154
3180
  agent: params.agent,
3155
3181
  sessionManager: params.sessionManager,
3156
3182
  messages: params.agent.state.messages.slice(),
3157
- cwd: params.cwd
3183
+ cwd: params.cwd,
3184
+ signal: params.signal
3158
3185
  });
3186
+ if (isAborted() || result?.aborted) {
3187
+ const aborted = { ...result, aborted: true };
3188
+ params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, result: aborted });
3189
+ return aborted;
3190
+ }
3159
3191
  if (result?.summary && result.firstKeptEntryId) {
3160
3192
  params.sessionManager.appendCompaction(result.summary, result.firstKeptEntryId, result.tokensBefore);
3161
3193
  params.replaceMessagesAndMarkSynced(params.sessionManager.getMessages());
3162
3194
  } else if (result?.messages) {
3163
3195
  params.replaceMessagesAndMarkSynced(result.messages, { updateSession: true });
3164
3196
  }
3197
+ if (isAborted()) {
3198
+ const aborted = { ...result, aborted: true };
3199
+ params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, result: aborted });
3200
+ return aborted;
3201
+ }
3165
3202
  params.markSyncedToAgentState();
3166
3203
  await params.sessionManager.save();
3204
+ if (isAborted()) {
3205
+ const aborted = { ...result, aborted: true };
3206
+ params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, result: aborted });
3207
+ return aborted;
3208
+ }
3167
3209
  if (params.willRetry && !result?.aborted) {
3168
3210
  await params.continueTurn();
3169
3211
  }
3170
3212
  params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, result });
3171
3213
  return result;
3172
3214
  } catch (error) {
3215
+ if (isAborted()) {
3216
+ const result = abortedResult();
3217
+ params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, result });
3218
+ return result;
3219
+ }
3173
3220
  const errorMessage = error instanceof Error ? error.message : String(error);
3174
3221
  params.emit({ type: "auto_compaction_end", reason: params.reason, willRetry: params.willRetry, errorMessage });
3175
3222
  throw error;
@@ -3685,6 +3732,9 @@ var AgentSessionRetryController = class {
3685
3732
  // ../../packages/agent-framework/src/session/controller/runtime-guard.ts
3686
3733
  var RUNAWAY_TOOLCALL_WHITESPACE_DELTA_CHARS = 16384;
3687
3734
  var RUNAWAY_TOOLCALL_WHITESPACE_DELTA_EVENTS = 40;
3735
+ var TOOL_FAILURE_SIGNATURE_CHARS = 1e3;
3736
+ var TOOL_FAILURE_SIGNATURE_CONTEXT_LINES = 5;
3737
+ var FAILURE_DIAGNOSTIC_LINE_PATTERN = /\b(E2E_FAILED|AssertionError|TimeoutError|SyntaxError|ReferenceError|TypeError|Error):|(^|\b)(failed|failure|timed out|timeout|exit code|command failed|npm ERR!)/i;
3688
3738
  function stableStringify(value) {
3689
3739
  if (value === null || typeof value !== "object") {
3690
3740
  return JSON.stringify(value) ?? String(value);
@@ -3703,6 +3753,20 @@ function summarizeToolResultForGuard(result) {
3703
3753
  const text = content.filter((block) => !!block && typeof block === "object" && "type" in block).filter((block) => block.type === "text").map((block) => block.text || "").join("\n").trim();
3704
3754
  return text || stableStringify(result);
3705
3755
  }
3756
+ function summarizeToolFailureSignature(result) {
3757
+ const summary = summarizeToolResultForGuard(result).replace(/\r\n/g, "\n").replace(/\r/g, "\n").trim();
3758
+ if (!summary) {
3759
+ return "";
3760
+ }
3761
+ const lines = summary.split("\n");
3762
+ for (let index = lines.length - 1; index >= 0; index--) {
3763
+ if (!FAILURE_DIAGNOSTIC_LINE_PATTERN.test(lines[index] ?? "")) {
3764
+ continue;
3765
+ }
3766
+ return lines.slice(index, Math.min(lines.length, index + TOOL_FAILURE_SIGNATURE_CONTEXT_LINES)).join("\n").slice(0, TOOL_FAILURE_SIGNATURE_CHARS);
3767
+ }
3768
+ return summary.slice(-TOOL_FAILURE_SIGNATURE_CHARS);
3769
+ }
3706
3770
  var AgentSessionRuntimeGuard = class {
3707
3771
  constructor(trigger) {
3708
3772
  this.trigger = trigger;
@@ -3767,7 +3831,7 @@ var AgentSessionRuntimeGuard = class {
3767
3831
  }
3768
3832
  return;
3769
3833
  }
3770
- const resultSummary = summarizeToolResultForGuard(event.result).slice(0, 500);
3834
+ const resultSummary = summarizeToolFailureSignature(event.result);
3771
3835
  const key = `${event.toolName}:${stableStringify(event.args)}:${resultSummary}`;
3772
3836
  const repeatCount = (this.repeatedToolFailures.get(key) ?? 0) + 1;
3773
3837
  this.repeatedToolFailures.set(key, repeatCount);
@@ -4009,6 +4073,7 @@ async function runAgentSessionControllerAutoCompact(params) {
4009
4073
  const result = await runAgentSessionCompaction({
4010
4074
  reason: params.reason,
4011
4075
  willRetry: params.willRetry,
4076
+ signal: params.signal,
4012
4077
  compaction: params.compaction,
4013
4078
  agent: params.agent,
4014
4079
  sessionManager: params.sessionManager,
@@ -4020,14 +4085,15 @@ async function runAgentSessionControllerAutoCompact(params) {
4020
4085
  continueTurn: params.continueTurn
4021
4086
  });
4022
4087
  if (!params.willRetry || result?.aborted) {
4088
+ const alreadyCancelled = params.getRecoveryState?.() === "cancelled" || params.getDisposed?.() === true;
4023
4089
  params.setRecoveryState(result?.aborted && cancelOnAbort ? "cancelled" : "none");
4024
4090
  if (result?.aborted) {
4025
4091
  params.cancelRetry();
4026
- if (cancelOnAbort) {
4092
+ if (cancelOnAbort && !alreadyCancelled) {
4027
4093
  params.emit({ type: "turn_cancelled", reason: "compaction_aborted" });
4028
4094
  }
4029
4095
  }
4030
- if (emitSettled) {
4096
+ if (emitSettled && !alreadyCancelled) {
4031
4097
  params.emit({ type: "turn_settled" });
4032
4098
  }
4033
4099
  if (!result?.aborted && runAfterAgentEndHook) {
@@ -4125,8 +4191,8 @@ var AgentSessionController = class {
4125
4191
  getDisposed: () => this.disposed,
4126
4192
  getRuntimeGuardTriggered: () => this.runtimeGuard.triggered,
4127
4193
  isStreaming: () => this.isStreaming,
4128
- runAutoCompact: async (decision) => {
4129
- await this.runAutoCompact(decision.reason, decision.willRetry);
4194
+ runAutoCompact: async (decision, signal) => {
4195
+ await this.runAutoCompact(decision.reason, decision.willRetry, { signal });
4130
4196
  }
4131
4197
  });
4132
4198
  this.autoContinue = new AgentSessionAutoContinueController({
@@ -4309,6 +4375,7 @@ var AgentSessionController = class {
4309
4375
  return runAgentSessionControllerAutoCompact({
4310
4376
  reason,
4311
4377
  willRetry,
4378
+ signal: options?.signal,
4312
4379
  compaction: this.compaction,
4313
4380
  agent: this.agent,
4314
4381
  sessionManager: this.sessionManager,
@@ -4318,6 +4385,8 @@ var AgentSessionController = class {
4318
4385
  setRecoveryState: (state) => {
4319
4386
  this.recoveryState = state;
4320
4387
  },
4388
+ getRecoveryState: () => this.recoveryState,
4389
+ getDisposed: () => this.disposed,
4321
4390
  cancelRetry: () => this.retryController.cancel(),
4322
4391
  clearPendingFailure: () => {
4323
4392
  this.pendingCompactionFailure = void 0;
@@ -5738,7 +5807,49 @@ function restoreLineEndings(text, ending) {
5738
5807
  return ending === "\r\n" ? text.replace(/\n/g, "\r\n") : text;
5739
5808
  }
5740
5809
  function normalizeForFuzzyMatch(text) {
5741
- return text.split("\n").map((line) => line.trimEnd()).join("\n").replace(/[\u2018\u2019\u201A\u201B]/g, "'").replace(/[\u201C\u201D\u201E\u201F]/g, '"').replace(/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/g, "-").replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " ");
5810
+ return buildFuzzyIndexMap(text).normalized;
5811
+ }
5812
+ function normalizeCharForFuzzyMatch(char) {
5813
+ if (/[\u2018\u2019\u201A\u201B]/.test(char)) return "'";
5814
+ if (/[\u201C\u201D\u201E\u201F]/.test(char)) return '"';
5815
+ if (/[\u2010\u2011\u2012\u2013\u2014\u2015\u2212]/.test(char)) return "-";
5816
+ if (/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/.test(char)) return " ";
5817
+ return char;
5818
+ }
5819
+ function buildFuzzyIndexMap(text) {
5820
+ const lines = text.split("\n");
5821
+ let normalized = "";
5822
+ const originalStartByNormalizedIndex = [];
5823
+ const originalEndByNormalizedIndex = [];
5824
+ let originalLineStart = 0;
5825
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
5826
+ const line = lines[lineIndex] ?? "";
5827
+ const trimmedLine = line.trimEnd();
5828
+ for (let index = 0; index < trimmedLine.length; index++) {
5829
+ normalized += normalizeCharForFuzzyMatch(trimmedLine[index]);
5830
+ originalStartByNormalizedIndex.push(originalLineStart + index);
5831
+ originalEndByNormalizedIndex.push(originalLineStart + index + 1);
5832
+ }
5833
+ if (lineIndex < lines.length - 1) {
5834
+ normalized += "\n";
5835
+ originalStartByNormalizedIndex.push(originalLineStart + line.length);
5836
+ originalEndByNormalizedIndex.push(originalLineStart + line.length + 1);
5837
+ }
5838
+ originalLineStart += line.length + (lineIndex < lines.length - 1 ? 1 : 0);
5839
+ }
5840
+ return { normalized, originalStartByNormalizedIndex, originalEndByNormalizedIndex };
5841
+ }
5842
+ function countOccurrences(content, needle) {
5843
+ if (needle.length === 0) return 0;
5844
+ let count = 0;
5845
+ let index = 0;
5846
+ while (true) {
5847
+ const nextIndex = content.indexOf(needle, index);
5848
+ if (nextIndex === -1) break;
5849
+ count++;
5850
+ index = nextIndex + needle.length;
5851
+ }
5852
+ return count;
5742
5853
  }
5743
5854
  function fuzzyFindText(content, oldText) {
5744
5855
  const exactIndex = content.indexOf(oldText);
@@ -5748,11 +5859,25 @@ function fuzzyFindText(content, oldText) {
5748
5859
  index: exactIndex,
5749
5860
  matchLength: oldText.length,
5750
5861
  usedFuzzyMatch: false,
5751
- contentForReplacement: content
5862
+ contentForReplacement: content,
5863
+ occurrences: countOccurrences(content, oldText),
5864
+ matchKind: "exact"
5752
5865
  };
5753
5866
  }
5754
- const fuzzyContent = normalizeForFuzzyMatch(content);
5867
+ const fuzzyMap = buildFuzzyIndexMap(content);
5868
+ const fuzzyContent = fuzzyMap.normalized;
5755
5869
  const fuzzyOldText = normalizeForFuzzyMatch(oldText);
5870
+ if (fuzzyOldText.length === 0) {
5871
+ return {
5872
+ found: false,
5873
+ index: -1,
5874
+ matchLength: 0,
5875
+ usedFuzzyMatch: false,
5876
+ contentForReplacement: content,
5877
+ occurrences: 0,
5878
+ matchKind: "none"
5879
+ };
5880
+ }
5756
5881
  const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);
5757
5882
  if (fuzzyIndex === -1) {
5758
5883
  return {
@@ -5760,35 +5885,65 @@ function fuzzyFindText(content, oldText) {
5760
5885
  index: -1,
5761
5886
  matchLength: 0,
5762
5887
  usedFuzzyMatch: false,
5763
- contentForReplacement: content
5888
+ contentForReplacement: content,
5889
+ occurrences: 0,
5890
+ matchKind: "none"
5764
5891
  };
5765
5892
  }
5893
+ const endFuzzyIndex = fuzzyIndex + fuzzyOldText.length - 1;
5894
+ const originalStart = fuzzyMap.originalStartByNormalizedIndex[fuzzyIndex];
5895
+ const originalEnd = fuzzyMap.originalEndByNormalizedIndex[endFuzzyIndex];
5766
5896
  return {
5767
5897
  found: true,
5768
- index: fuzzyIndex,
5769
- matchLength: fuzzyOldText.length,
5898
+ index: originalStart,
5899
+ matchLength: originalEnd - originalStart,
5770
5900
  usedFuzzyMatch: true,
5771
- contentForReplacement: fuzzyContent
5901
+ contentForReplacement: content,
5902
+ occurrences: countOccurrences(fuzzyContent, fuzzyOldText),
5903
+ matchKind: "fuzzy"
5772
5904
  };
5773
5905
  }
5774
5906
  function stripBom(content) {
5775
5907
  return content.startsWith("\uFEFF") ? { bom: "\uFEFF", text: content.slice(1) } : { bom: "", text: content };
5776
5908
  }
5777
- function generateDiffString(oldContent, newContent, _contextLines = 4) {
5778
- const oldLines = oldContent.split("\n");
5779
- const newLines = newContent.split("\n");
5780
- let firstChangedLine;
5781
- for (let i = 0; i < Math.max(oldLines.length, newLines.length); i++) {
5782
- if (oldLines[i] !== newLines[i]) {
5783
- firstChangedLine = i + 1;
5784
- break;
5785
- }
5786
- }
5787
- const diff = `--- old
5788
- +++ new
5789
- @@ -1,${oldLines.length} +1,${newLines.length} @@
5790
- [Diff: ${oldLines.length} lines -> ${newLines.length} lines]`;
5791
- return { diff, firstChangedLine };
5909
+ function generateDiffString(oldContent, newContent, contextLines = 4) {
5910
+ const oldLines = normalizeToLF(stripBom(oldContent).text).split("\n");
5911
+ const newLines = normalizeToLF(stripBom(newContent).text).split("\n");
5912
+ let prefixLength = 0;
5913
+ while (prefixLength < oldLines.length && prefixLength < newLines.length && oldLines[prefixLength] === newLines[prefixLength]) {
5914
+ prefixLength++;
5915
+ }
5916
+ if (prefixLength === oldLines.length && prefixLength === newLines.length) {
5917
+ return { diff: "--- old\n+++ new\n", firstChangedLine: void 0 };
5918
+ }
5919
+ let oldSuffixIndex = oldLines.length - 1;
5920
+ let newSuffixIndex = newLines.length - 1;
5921
+ while (oldSuffixIndex >= prefixLength && newSuffixIndex >= prefixLength && oldLines[oldSuffixIndex] === newLines[newSuffixIndex]) {
5922
+ oldSuffixIndex--;
5923
+ newSuffixIndex--;
5924
+ }
5925
+ const beforeContext = Math.min(contextLines, prefixLength);
5926
+ const removedCount = Math.max(0, oldSuffixIndex - prefixLength + 1);
5927
+ const addedCount = Math.max(0, newSuffixIndex - prefixLength + 1);
5928
+ const afterContext = Math.min(contextLines, oldLines.length - oldSuffixIndex - 1, newLines.length - newSuffixIndex - 1);
5929
+ const hunkOldStart = Math.max(0, prefixLength - beforeContext);
5930
+ const hunkNewStart = Math.max(0, prefixLength - beforeContext);
5931
+ const hunkOldCount = beforeContext + removedCount + afterContext;
5932
+ const hunkNewCount = beforeContext + addedCount + afterContext;
5933
+ const lines = ["--- old", "+++ new", `@@ -${hunkOldStart + 1},${hunkOldCount} +${hunkNewStart + 1},${hunkNewCount} @@`];
5934
+ for (let index = prefixLength - beforeContext; index < prefixLength; index++) {
5935
+ lines.push(` ${oldLines[index] ?? ""}`);
5936
+ }
5937
+ for (let index = prefixLength; index <= oldSuffixIndex; index++) {
5938
+ lines.push(`-${oldLines[index] ?? ""}`);
5939
+ }
5940
+ for (let index = prefixLength; index <= newSuffixIndex; index++) {
5941
+ lines.push(`+${newLines[index] ?? ""}`);
5942
+ }
5943
+ for (let offset = 1; offset <= afterContext; offset++) {
5944
+ lines.push(` ${oldLines[oldSuffixIndex + offset] ?? ""}`);
5945
+ }
5946
+ return { diff: lines.join("\n"), firstChangedLine: prefixLength + 1 };
5792
5947
  }
5793
5948
 
5794
5949
  // ../../packages/shared-headless-capabilities/src/builtin/fs/edit.ts
@@ -5810,7 +5965,7 @@ function validateEditArgs(path3, oldText, newText) {
5810
5965
  throw new Error("Invalid edit_file arguments: path, oldText, and newText must be real edit values, not tool-call markup.");
5811
5966
  }
5812
5967
  }
5813
- function countOccurrences(content, needle) {
5968
+ function countOccurrences2(content, needle) {
5814
5969
  if (needle.length === 0) return 0;
5815
5970
  let count = 0;
5816
5971
  let index = 0;
@@ -5822,6 +5977,29 @@ function countOccurrences(content, needle) {
5822
5977
  }
5823
5978
  return count;
5824
5979
  }
5980
+ function createEditErrorResult(params) {
5981
+ const detailLines = [
5982
+ params.message,
5983
+ params.recoveryHint,
5984
+ params.alreadyAppliedCandidate ? "Diagnostic: newText already appears in the current file, but edit_file did not treat that as success because it may be an unrelated occurrence." : ""
5985
+ ].filter(Boolean);
5986
+ return {
5987
+ content: [{ type: "text", text: detailLines.join("\n") }],
5988
+ details: {
5989
+ status: "error",
5990
+ matchKind: params.matchKind,
5991
+ changed: false,
5992
+ diff: "",
5993
+ oldTextOccurrences: params.oldTextOccurrences,
5994
+ newTextOccurrences: params.newTextOccurrences,
5995
+ errorReason: params.errorReason,
5996
+ recoveryHint: params.recoveryHint,
5997
+ staleBaseLikely: params.staleBaseLikely,
5998
+ alreadyAppliedCandidate: params.alreadyAppliedCandidate
5999
+ },
6000
+ isError: true
6001
+ };
6002
+ }
5825
6003
  function createEditTool(cwd, options) {
5826
6004
  const fs2 = getFileSystem();
5827
6005
  const rootSchema = buildRootParameterSchema(cwd, options);
@@ -5871,37 +6049,53 @@ function createEditTool(cwd, options) {
5871
6049
  const normalizedContent = normalizeToLF(content);
5872
6050
  const normalizedOldText = normalizeToLF(oldText);
5873
6051
  const normalizedNewText = normalizeToLF(newText);
6052
+ const newTextOccurrences = countOccurrences2(normalizedContent, normalizedNewText);
5874
6053
  const matchResult = fuzzyFindText(normalizedContent, normalizedOldText);
5875
6054
  if (!matchResult.found) {
5876
6055
  if (signal) signal.removeEventListener("abort", onAbort);
5877
- reject(
5878
- new Error(
5879
- `Could not find the exact text in ${path3}. The old text must match exactly including all whitespace and newlines.`
5880
- )
6056
+ resolve2(
6057
+ createEditErrorResult({
6058
+ message: `Could not find oldText in ${path3}.`,
6059
+ matchKind: "none",
6060
+ errorReason: "old_text_not_found",
6061
+ oldTextOccurrences: 0,
6062
+ newTextOccurrences,
6063
+ staleBaseLikely: newTextOccurrences > 0,
6064
+ alreadyAppliedCandidate: newTextOccurrences > 0,
6065
+ recoveryHint: newTextOccurrences > 0 ? "The replacement text already appears in the current file. Read the current file before retrying; this may be a stale oldText from an earlier edit in the same turn." : "Read the current file and retry with a larger exact block copied from the latest file contents."
6066
+ })
5881
6067
  );
5882
6068
  return;
5883
6069
  }
5884
- const fuzzyContent = normalizeForFuzzyMatch(normalizedContent);
5885
- const fuzzyOldText = normalizeForFuzzyMatch(normalizedOldText);
5886
- const occurrences = countOccurrences(fuzzyContent, fuzzyOldText);
5887
- if (occurrences > 1) {
6070
+ if (matchResult.occurrences > 1) {
5888
6071
  if (signal) signal.removeEventListener("abort", onAbort);
5889
- reject(
5890
- new Error(
5891
- `Found ${occurrences} occurrences of the text in ${path3}. The text must be unique. Please provide more context to make it unique.`
5892
- )
6072
+ resolve2(
6073
+ createEditErrorResult({
6074
+ message: `Found ${matchResult.occurrences} occurrences of oldText in ${path3}. The text must be unique.`,
6075
+ matchKind: matchResult.matchKind,
6076
+ errorReason: "old_text_not_unique",
6077
+ oldTextOccurrences: matchResult.occurrences,
6078
+ newTextOccurrences,
6079
+ recoveryHint: "Read the current file and retry with a larger exact block that uniquely identifies the intended location."
6080
+ })
5893
6081
  );
5894
6082
  return;
5895
6083
  }
5896
6084
  if (aborted) return;
5897
- const baseContent = matchResult.contentForReplacement;
6085
+ const baseContent = normalizedContent;
5898
6086
  const newContent = baseContent.substring(0, matchResult.index) + normalizedNewText + baseContent.substring(matchResult.index + matchResult.matchLength);
5899
6087
  if (baseContent === newContent) {
5900
6088
  if (signal) signal.removeEventListener("abort", onAbort);
5901
- reject(
5902
- new Error(
5903
- `No changes made to ${path3}. The replacement produced identical content.`
5904
- )
6089
+ resolve2(
6090
+ createEditErrorResult({
6091
+ message: `No changes made to ${path3}. The replacement produced identical content.`,
6092
+ matchKind: matchResult.matchKind,
6093
+ errorReason: "replacement_no_change",
6094
+ oldTextOccurrences: matchResult.occurrences,
6095
+ newTextOccurrences,
6096
+ recoveryHint: "Read the current file and verify whether the intended edit is already present or whether oldText/newText need a larger exact block.",
6097
+ alreadyAppliedCandidate: newTextOccurrences > 0
6098
+ })
5905
6099
  );
5906
6100
  return;
5907
6101
  }
@@ -5911,16 +6105,24 @@ function createEditTool(cwd, options) {
5911
6105
  if (signal) {
5912
6106
  signal.removeEventListener("abort", onAbort);
5913
6107
  }
5914
- const diffResult = generateDiffString(content, finalContent);
6108
+ const diffResult = generateDiffString(content, restoreLineEndings(newContent, originalEnding));
5915
6109
  resolve2({
5916
6110
  content: [
5917
6111
  {
5918
6112
  type: "text",
5919
- text: `Successfully replaced text in ${path3}.`
6113
+ text: `Successfully replaced text in ${path3} using ${matchResult.matchKind} match.`
5920
6114
  },
5921
6115
  { type: "text", text: diffResult.diff }
5922
6116
  ],
5923
- details: { diff: diffResult.diff, firstChangedLine: diffResult.firstChangedLine }
6117
+ details: {
6118
+ status: "success",
6119
+ matchKind: matchResult.matchKind,
6120
+ changed: true,
6121
+ diff: diffResult.diff,
6122
+ firstChangedLine: diffResult.firstChangedLine,
6123
+ oldTextOccurrences: matchResult.occurrences,
6124
+ newTextOccurrences
6125
+ }
5924
6126
  });
5925
6127
  } catch (error) {
5926
6128
  if (signal) {
@@ -6974,6 +7176,145 @@ function createEmptyRuntimeSummary() {
6974
7176
  toolErrors: 0
6975
7177
  };
6976
7178
  }
7179
+ function summarizeString(value, maxLength = 300) {
7180
+ return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
7181
+ }
7182
+ function summarizeMessage(message) {
7183
+ if (!isRecord(message)) return typeof message;
7184
+ if ("contentBlocks" in message && !("content" in message)) return message;
7185
+ const content = Array.isArray(message.content) ? message.content : [];
7186
+ const blockTypes = content.filter(isRecord).map((block) => String(block.type || "unknown")).slice(0, 10);
7187
+ const text = getTextFromMessageContent(content);
7188
+ return {
7189
+ role: message.role,
7190
+ stopReason: message.stopReason,
7191
+ errorMessage: typeof message.errorMessage === "string" ? summarizeString(message.errorMessage) : void 0,
7192
+ contentBlocks: content.length,
7193
+ blockTypes,
7194
+ textLength: text.length
7195
+ };
7196
+ }
7197
+ function summarizeToolResults(value) {
7198
+ if (isRecord(value) && typeof value.count === "number" && !Array.isArray(value)) return value;
7199
+ if (!Array.isArray(value)) return typeof value;
7200
+ let errors = 0;
7201
+ const toolNames = [];
7202
+ for (const result of value) {
7203
+ if (!isRecord(result)) continue;
7204
+ if (result.isError === true) errors++;
7205
+ const toolName = typeof result.toolName === "string" ? result.toolName : typeof result.name === "string" ? result.name : void 0;
7206
+ if (toolName && toolNames.length < 10) toolNames.push(toolName);
7207
+ }
7208
+ return { count: value.length, errors, toolNames };
7209
+ }
7210
+ function collectTextLength(content) {
7211
+ if (typeof content === "string") return content.length;
7212
+ if (!Array.isArray(content)) return 0;
7213
+ let length = 0;
7214
+ for (const block of content) {
7215
+ if (!isRecord(block)) continue;
7216
+ if (typeof block.text === "string") length += block.text.length;
7217
+ }
7218
+ return length;
7219
+ }
7220
+ function collectArgumentLength(content) {
7221
+ if (!Array.isArray(content)) return 0;
7222
+ let length = 0;
7223
+ for (const block of content) {
7224
+ if (!isRecord(block) || !("arguments" in block)) continue;
7225
+ if (typeof block.arguments === "string") {
7226
+ length += block.arguments.length;
7227
+ continue;
7228
+ }
7229
+ try {
7230
+ length += JSON.stringify(block.arguments).length;
7231
+ } catch {
7232
+ length += String(block.arguments).length;
7233
+ }
7234
+ }
7235
+ return length;
7236
+ }
7237
+ function summarizeMessages(value) {
7238
+ if (!Array.isArray(value)) return typeof value;
7239
+ const roles = [];
7240
+ const toolNames = [];
7241
+ const stopReasons = [];
7242
+ let errorCount = 0;
7243
+ let contentBlocks = 0;
7244
+ let textLength = 0;
7245
+ let argumentLength = 0;
7246
+ for (const message of value) {
7247
+ if (!isRecord(message)) continue;
7248
+ const role = typeof message.role === "string" ? message.role : void 0;
7249
+ if (role && roles.length < 20) roles.push(role);
7250
+ if (typeof message.stopReason === "string" && stopReasons.length < 20) stopReasons.push(message.stopReason);
7251
+ if (typeof message.errorMessage === "string" && message.errorMessage) errorCount++;
7252
+ if (typeof message.toolName === "string" && toolNames.length < 20) toolNames.push(message.toolName);
7253
+ const content = Array.isArray(message.content) ? message.content : [];
7254
+ contentBlocks += content.length;
7255
+ textLength += collectTextLength(message.content);
7256
+ argumentLength += collectArgumentLength(message.content);
7257
+ for (const block of content) {
7258
+ if (isRecord(block) && typeof block.name === "string" && toolNames.length < 20) {
7259
+ toolNames.push(block.name);
7260
+ }
7261
+ }
7262
+ }
7263
+ return {
7264
+ count: value.length,
7265
+ roles,
7266
+ toolNames: [...new Set(toolNames)].slice(0, 20),
7267
+ stopReasons: [...new Set(stopReasons)].slice(0, 20),
7268
+ errorCount,
7269
+ contentBlocks,
7270
+ textLength,
7271
+ argumentLength
7272
+ };
7273
+ }
7274
+ function summarizeFailure(value) {
7275
+ if (!isRecord(value)) return typeof value;
7276
+ return {
7277
+ kind: value.kind,
7278
+ retryable: value.retryable,
7279
+ compactable: value.compactable,
7280
+ userAbort: value.userAbort,
7281
+ terminal: value.terminal,
7282
+ message: typeof value.message === "string" ? summarizeString(value.message) : void 0
7283
+ };
7284
+ }
7285
+ function summarizeRuntimeEvent(value) {
7286
+ if (!isRecord(value)) return typeof value;
7287
+ const summary = {
7288
+ type: value.type
7289
+ };
7290
+ if ("toolCallId" in value) summary.toolCallId = value.toolCallId;
7291
+ if ("toolName" in value) summary.toolName = value.toolName;
7292
+ if ("turnIndex" in value) summary.turnIndex = value.turnIndex;
7293
+ if ("isError" in value) summary.isError = value.isError;
7294
+ if ("errorMessage" in value && typeof value.errorMessage === "string") {
7295
+ summary.errorMessage = summarizeString(value.errorMessage);
7296
+ }
7297
+ if ("message" in value) summary.message = summarizeMessage(value.message);
7298
+ if ("toolResults" in value) summary.toolResults = summarizeToolResults(value.toolResults);
7299
+ return summary;
7300
+ }
7301
+ function shouldRecordRuntimeEvent(type) {
7302
+ const normalizedType = type.startsWith("runtime:") ? type.slice("runtime:".length) : type;
7303
+ return normalizedType !== "agent_event" && normalizedType !== "semantic_event";
7304
+ }
7305
+ function recomputeRuntimeSummaryFromTimeline(events) {
7306
+ const summary = createEmptyRuntimeSummary();
7307
+ for (const event of events ?? []) {
7308
+ if (/queue|queued_turn/.test(event.type)) summary.queuedTurnEvents++;
7309
+ if (/retry/.test(event.type)) summary.retryEvents++;
7310
+ if (/auto_compaction|auto_compact|compaction/.test(event.type)) summary.autoCompactionEvents++;
7311
+ if (/runtime_guard|repeated_tool_error/.test(event.type)) summary.runtimeGuardEvents++;
7312
+ if (/subagent/.test(event.type)) summary.subagentEvents++;
7313
+ if (event.type === "tool_end" || event.type === "tool_error") summary.toolResults++;
7314
+ if (event.type === "tool_error") summary.toolErrors++;
7315
+ }
7316
+ return summary;
7317
+ }
6977
7318
  function summarizeMeta(meta) {
6978
7319
  if (!isRecord(meta)) return meta;
6979
7320
  const summary = {};
@@ -6982,6 +7323,26 @@ function summarizeMeta(meta) {
6982
7323
  summary[key] = Array.isArray(value) ? { count: value.length } : typeof value;
6983
7324
  continue;
6984
7325
  }
7326
+ if (key === "addedMessages") {
7327
+ summary[key] = summarizeMessages(value);
7328
+ continue;
7329
+ }
7330
+ if (key === "message") {
7331
+ summary[key] = summarizeMessage(value);
7332
+ continue;
7333
+ }
7334
+ if (key === "toolResults") {
7335
+ summary[key] = summarizeToolResults(value);
7336
+ continue;
7337
+ }
7338
+ if (key === "failure") {
7339
+ summary[key] = summarizeFailure(value);
7340
+ continue;
7341
+ }
7342
+ if (key === "event") {
7343
+ summary[key] = summarizeRuntimeEvent(value);
7344
+ continue;
7345
+ }
6985
7346
  if (key === "queuedInput" && isRecord(value)) {
6986
7347
  summary[key] = {
6987
7348
  mode: value.mode,
@@ -6991,7 +7352,7 @@ function summarizeMeta(meta) {
6991
7352
  };
6992
7353
  continue;
6993
7354
  }
6994
- summary[key] = typeof value === "string" && value.length > 300 ? `${value.slice(0, 300)}...` : value;
7355
+ summary[key] = typeof value === "string" ? summarizeString(value) : value;
6995
7356
  }
6996
7357
  return summary;
6997
7358
  }
@@ -7105,9 +7466,7 @@ function timelineEventFromTraceEvent(type, meta) {
7105
7466
  failure: typeof data.failureCategory === "string" && data.failureCategory.length > 0
7106
7467
  };
7107
7468
  }
7108
- if (normalizedType === "subagent_summary") {
7109
- return { type: "subagent_child_end", summary: `subagent summary count=${String(data.count ?? "?")}`, details: detail };
7110
- }
7469
+ if (normalizedType === "subagent_summary") return null;
7111
7470
  return null;
7112
7471
  }
7113
7472
  function cloneTurn(turn) {
@@ -7148,6 +7507,9 @@ var SessionTraceController = class {
7148
7507
  if (!Array.isArray(this.trace.recentTimeline)) {
7149
7508
  this.trace.recentTimeline = [];
7150
7509
  }
7510
+ this.trace.recentEvents = this.trace.recentEvents.slice(-this.recentEventsLimit);
7511
+ this.trace.recentTimeline = this.trace.recentTimeline.slice(-this.recentEventsLimit);
7512
+ this.trace.runtimeSummary = recomputeRuntimeSummaryFromTimeline(this.trace.recentTimeline);
7151
7513
  }
7152
7514
  trace;
7153
7515
  recentTurnsLimit;
@@ -7162,7 +7524,6 @@ var SessionTraceController = class {
7162
7524
  if (this.trace.recentEvents.length > this.recentEventsLimit) {
7163
7525
  this.trace.recentEvents = this.trace.recentEvents.slice(-this.recentEventsLimit);
7164
7526
  }
7165
- this.updateRuntimeSummary(type, meta);
7166
7527
  const timelineEvent = timelineEventFromTraceEvent(type, meta);
7167
7528
  if (timelineEvent) {
7168
7529
  this.pushTimeline(timelineEvent);
@@ -7177,17 +7538,7 @@ var SessionTraceController = class {
7177
7538
  if (this.trace.recentTimeline.length > this.recentEventsLimit) {
7178
7539
  this.trace.recentTimeline = this.trace.recentTimeline.slice(-this.recentEventsLimit);
7179
7540
  }
7180
- }
7181
- updateRuntimeSummary(type, meta) {
7182
- const summary = this.trace.runtimeSummary ?? createEmptyRuntimeSummary();
7183
- if (/queue|queued_turn/.test(type)) summary.queuedTurnEvents++;
7184
- if (/retry/.test(type)) summary.retryEvents++;
7185
- if (/auto_compaction|auto_compact|compaction/.test(type)) summary.autoCompactionEvents++;
7186
- if (/runtime_guard|repeated_tool_error/.test(type)) summary.runtimeGuardEvents++;
7187
- if (/subagent/.test(type)) summary.subagentEvents++;
7188
- if (type === "tool_end") summary.toolResults++;
7189
- if (type === "tool_end" && isRecord(meta) && meta.isError) summary.toolErrors++;
7190
- this.trace.runtimeSummary = summary;
7541
+ this.trace.runtimeSummary = recomputeRuntimeSummaryFromTimeline(this.trace.recentTimeline);
7191
7542
  }
7192
7543
  nextTurnIndex() {
7193
7544
  if (this.trace.activeTurn) {
@@ -7259,6 +7610,7 @@ var SessionTraceController = class {
7259
7610
  this.touch();
7260
7611
  }
7261
7612
  noteRuntimeEvent(type, meta) {
7613
+ if (!shouldRecordRuntimeEvent(type)) return;
7262
7614
  this.pushEvent(`runtime:${type}`, summarizeMeta(meta));
7263
7615
  this.touch();
7264
7616
  }
@@ -7283,7 +7635,6 @@ var SessionTraceController = class {
7283
7635
  if (!message || message.role !== "assistant" || !this.trace.activeTurn) return;
7284
7636
  this.trace.activeTurn.state = this.trace.activeTurn.toolCalls.some((tool) => tool.status === "running") ? "tool_running" : "streaming";
7285
7637
  this.trace.activeTurn.assistantText = getTextFromMessageContent(message.content);
7286
- this.pushEvent("assistant_update");
7287
7638
  this.touch();
7288
7639
  }
7289
7640
  startTool(toolCallId, toolName, args) {
@@ -8,7 +8,7 @@ import {
8
8
  createSharedWebSearchTool,
9
9
  interpretShellExit,
10
10
  requestInteraction
11
- } from "./chunk-7GAYJ6AF.js";
11
+ } from "./chunk-G4GV2CRT.js";
12
12
  import {
13
13
  Type
14
14
  } from "./chunk-5DA2D3K2.js";
package/dist/cli.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  getSettingsPath,
15
15
  getThemesDir,
16
16
  migrateConfigFromAgentDir
17
- } from "./chunks/chunk-62XU6P2H.js";
17
+ } from "./chunks/chunk-MHFUWY7I.js";
18
18
  import {
19
19
  AGENTS_CONTEXT_FILE_NAME,
20
20
  AgentSessionController,
@@ -55,7 +55,7 @@ import {
55
55
  selectToolsForRuntimePolicy,
56
56
  shouldPreserveExecutionStateForUserText,
57
57
  supersedeExecutionState
58
- } from "./chunks/chunk-7GAYJ6AF.js";
58
+ } from "./chunks/chunk-G4GV2CRT.js";
59
59
  import "./chunks/chunk-VE2HDCNB.js";
60
60
  import {
61
61
  Deref,
@@ -59550,6 +59550,26 @@ ${theme.fg("muted", "Receiving edit parameters...")}`;
59550
59550
 
59551
59551
  ${theme.fg("error", errorText)}`;
59552
59552
  }
59553
+ } else if (this.result?.details?.diff && rawPath) {
59554
+ const diff = this.result.details.diff;
59555
+ const firstChangedLine = this.result.details.firstChangedLine;
59556
+ if (firstChangedLine) {
59557
+ text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path27 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
59558
+ }
59559
+ const lines = diff.split("\n");
59560
+ const maxLines = this.expanded ? lines.length : 15;
59561
+ const displayLines = lines.slice(0, maxLines);
59562
+ const remaining = lines.length - maxLines;
59563
+ text += "\n\n" + displayLines.map((line) => {
59564
+ if (line.startsWith("+")) return theme.fg("success", line);
59565
+ if (line.startsWith("-")) return theme.fg("error", line);
59566
+ if (line.startsWith("@@")) return theme.fg("warning", line);
59567
+ return theme.fg("toolOutput", line);
59568
+ }).join("\n");
59569
+ if (remaining > 0) {
59570
+ text += theme.fg("muted", `
59571
+ ... (${remaining} more lines, press Ctrl+O to expand)`);
59572
+ }
59553
59573
  } else if (hasOldText && hasNewText && rawPath) {
59554
59574
  const diff = generateEditDiff(oldText, newText, rawPath);
59555
59575
  const firstChangedLine = findFirstChangedLine(oldText, newText);
@@ -64117,6 +64137,9 @@ function shouldCliAutoCompactTokens(params) {
64117
64137
  return tokenLimit !== void 0 && params.tokens > tokenLimit;
64118
64138
  }
64119
64139
  async function createCliAutoCompactionResult(params) {
64140
+ if (params.context.signal?.aborted) {
64141
+ return { aborted: true };
64142
+ }
64120
64143
  const activeEntryId = params.context.sessionManager.getActiveEntryId();
64121
64144
  if (!activeEntryId) {
64122
64145
  return { aborted: true };
@@ -64129,9 +64152,13 @@ async function createCliAutoCompactionResult(params) {
64129
64152
  const compactOptions = {
64130
64153
  model: params.model,
64131
64154
  apiKey: params.apiKey,
64132
- systemPrompt: params.systemPrompt
64155
+ systemPrompt: params.systemPrompt,
64156
+ signal: params.context.signal
64133
64157
  };
64134
64158
  const summary = await createCompactionSummary(params.context.messages, compactOptions);
64159
+ if (params.context.signal?.aborted) {
64160
+ return { aborted: true };
64161
+ }
64135
64162
  return {
64136
64163
  summary,
64137
64164
  firstKeptEntryId,
@@ -68035,6 +68062,18 @@ async function runJsonEventsMode(params) {
68035
68062
  break;
68036
68063
  }
68037
68064
  }
68065
+ function rememberTerminal(kind, detail, options) {
68066
+ if (!activeTurn || activeTurn.finalized) return;
68067
+ if (activeTurn.pendingTerminal && options?.overwrite === false) return;
68068
+ activeTurn.pendingTerminal = { kind, detail };
68069
+ touch();
68070
+ }
68071
+ function finalizePendingTerminal() {
68072
+ if (!activeTurn || activeTurn.finalized) return;
68073
+ const pending = activeTurn.pendingTerminal;
68074
+ if (!pending) return;
68075
+ finalize(pending.kind, pending.detail);
68076
+ }
68038
68077
  function handleSemanticEvent(event) {
68039
68078
  if (!activeTurn || activeTurn.finalized) return;
68040
68079
  switch (event.type) {
@@ -68082,6 +68121,7 @@ async function runJsonEventsMode(params) {
68082
68121
  function handleControllerEvent(event) {
68083
68122
  trace?.noteRuntimeEvent(event.type, event);
68084
68123
  if (event.type === "turn_settled" && activeTurn) {
68124
+ finalizePendingTerminal();
68085
68125
  writeEvent({
68086
68126
  type: "turn.settled",
68087
68127
  sessionId: activeTurn.sessionId,
@@ -68166,7 +68206,7 @@ async function runJsonEventsMode(params) {
68166
68206
  } else if (event.type === "turn_completed") {
68167
68207
  const text = assistantTextFromMessage(event.message);
68168
68208
  flushAssistantOutput(text);
68169
- finalize("completed", text || activeTurn.summary.trim());
68209
+ rememberTerminal("completed", text || activeTurn.summary.trim());
68170
68210
  } else if (event.type === "turn_failed_terminal") {
68171
68211
  touch();
68172
68212
  if (lastRetryEvent) {
@@ -68181,9 +68221,9 @@ async function runJsonEventsMode(params) {
68181
68221
  });
68182
68222
  lastRetryEvent = void 0;
68183
68223
  }
68184
- finalize("failed", event.failure.message);
68224
+ rememberTerminal("failed", event.failure.message);
68185
68225
  } else if (event.type === "turn_cancelled") {
68186
- finalize("cancelled", event.reason);
68226
+ rememberTerminal("cancelled", event.reason, { overwrite: false });
68187
68227
  }
68188
68228
  }
68189
68229
  async function ensureRuntime() {
@@ -68359,6 +68399,7 @@ async function runJsonEventsMode(params) {
68359
68399
  trace?.noteWaitForIdleStart({ mode: "json-events" });
68360
68400
  await controller.waitForSettled();
68361
68401
  trace?.noteWaitForIdleSettled({ mode: "json-events" });
68402
+ finalizePendingTerminal();
68362
68403
  if (!activeTurn?.finalized) {
68363
68404
  const finalError = assistantErrorFromAgent(agent);
68364
68405
  if (activeTurn?.interrupted) {
@@ -68434,7 +68475,11 @@ async function runJsonEventsMode(params) {
68434
68475
  if (activeTurn && !activeTurn.finalized) {
68435
68476
  activeTurn.interrupted = true;
68436
68477
  controller?.abort();
68437
- finalize("cancelled", message.reason || "shutdown");
68478
+ if (!controller) {
68479
+ finalize("cancelled", message.reason || "shutdown");
68480
+ } else {
68481
+ rememberTerminal("cancelled", message.reason || "shutdown");
68482
+ }
68438
68483
  }
68439
68484
  break;
68440
68485
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cydm/pie",
3
- "version": "1.0.16",
3
+ "version": "1.0.18",
4
4
  "description": "Pie AI Agent CLI",
5
5
  "type": "module",
6
6
  "bin": {