

























@@ -104,55 +104,55 @@ function expectToolResultWasTrimmed(result: AgentMessage[]) {
104104}
105105106106describe("pruneContextMessages", () => {
107-it("does not crash on assistant message with malformed thinking block (missing thinking string)", () => {
107+it("keeps assistant messages with malformed thinking blocks", () => {
108108const messages: AgentMessage[] = [
109109makeUser("hello"),
110110makeAssistant([
111111{ type: "thinking" } as unknown as AssistantContentBlock,
112112{ type: "text", text: "ok" },
113113]),
114114];
115-expect(() =>
116-pruneContextMessages({
117- messages,
118- settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
119- ctx: CONTEXT_WINDOW_1M,
120- }),
121-).not.toThrow();
115+const result = pruneContextMessages({
116+messages,
117+settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
118+ctx: CONTEXT_WINDOW_1M,
119+});
120+121+expect(result).toHaveLength(2);
122122});
123123124-it("does not crash on assistant message with null content entries", () => {
124+it("keeps assistant messages with null content entries", () => {
125125const messages: AgentMessage[] = [
126126makeUser("hello"),
127127makeAssistant([null as unknown as AssistantContentBlock, { type: "text", text: "world" }]),
128128];
129-expect(() =>
130-pruneContextMessages({
131- messages,
132- settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
133- ctx: CONTEXT_WINDOW_1M,
134- }),
135-).not.toThrow();
129+const result = pruneContextMessages({
130+messages,
131+settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
132+ctx: CONTEXT_WINDOW_1M,
133+});
134+135+expect(result).toHaveLength(2);
136136});
137137138-it("does not crash on assistant message with malformed text block (missing text string)", () => {
138+it("keeps assistant messages with malformed text blocks", () => {
139139const messages: AgentMessage[] = [
140140makeUser("hello"),
141141makeAssistant([
142142{ type: "text" } as unknown as AssistantContentBlock,
143143{ type: "thinking", thinking: "still fine" },
144144]),
145145];
146-expect(() =>
147-pruneContextMessages({
148- messages,
149- settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
150- ctx: CONTEXT_WINDOW_1M,
151- }),
152-).not.toThrow();
146+const result = pruneContextMessages({
147+messages,
148+settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
149+ctx: CONTEXT_WINDOW_1M,
150+});
151+152+expect(result).toHaveLength(2);
153153});
154154155-it("does not crash on toolResult with malformed text block (missing text string)", () => {
155+it("keeps tool results with malformed text blocks", () => {
156156// Regression: a plugin returning undefined produces {type: "text"} with no text property,
157157// which crashed estimateTextAndImageChars / collectTextSegments / collectPrunableToolResultSegments.
158158// See https://github.com/openclaw/openclaw/issues/34979
@@ -174,16 +174,16 @@ describe("pruneContextMessages", () => {
174174makeAssistant([{ type: "text", text: "done" }]),
175175];
176176177-expect(() =>
178-pruneContextMessages({
179- messages,
180- settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
181- ctx: CONTEXT_WINDOW_1M,
182- }),
183-).not.toThrow();
177+const result = pruneContextMessages({
178+messages,
179+settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
180+ctx: CONTEXT_WINDOW_1M,
181+});
182+183+expect(result).toHaveLength(5);
184184});
185185186-it("does not crash on toolResult with malformed text block during soft-trim (image path)", () => {
186+it("keeps tool results with malformed text blocks during soft-trim image paths", () => {
187187// The collectPrunableToolResultSegments path is exercised when the tool result
188188// contains image blocks alongside a malformed text block.
189189const malformedToolResult = {
@@ -199,28 +199,28 @@ describe("pruneContextMessages", () => {
199199makeAssistant([{ type: "text", text: "here it is" }]),
200200];
201201202-expect(() =>
203-pruneContextMessages({
204- messages,
205-settings: {
206- ...DEFAULT_CONTEXT_PRUNING_SETTINGS,
207-keepLastAssistants: 1,
208-softTrimRatio: 0,
209-hardClear: {
210- ...DEFAULT_CONTEXT_PRUNING_SETTINGS.hardClear,
211-enabled: false,
212-},
213-softTrim: {
214-maxChars: 5_000,
215-headChars: 2_000,
216-tailChars: 2_000,
217-},
202+const result = pruneContextMessages({
203+ messages,
204+settings: {
205+ ...DEFAULT_CONTEXT_PRUNING_SETTINGS,
206+keepLastAssistants: 1,
207+softTrimRatio: 0,
208+hardClear: {
209+ ...DEFAULT_CONTEXT_PRUNING_SETTINGS.hardClear,
210+enabled: false,
211+},
212+softTrim: {
213+maxChars: 5_000,
214+headChars: 2_000,
215+tailChars: 2_000,
218216},
219-ctx: CONTEXT_WINDOW_1M,
220-isToolPrunable: () => true,
221-contextWindowTokensOverride: 1,
222-}),
223-).not.toThrow();
217+},
218+ctx: CONTEXT_WINDOW_1M,
219+isToolPrunable: () => true,
220+contextWindowTokensOverride: 1,
221+});
222+223+expect(result).toHaveLength(3);
224224});
225225226226it("counts malformed non-string text blocks when deciding to trim tool results", () => {
@@ -264,7 +264,7 @@ describe("pruneContextMessages", () => {
264264expect(textBlock.text).toContain("[Tool result trimmed:");
265265});
266266267-it("does not crash on toolResult with null content entries", () => {
267+it("keeps tool results with null content entries", () => {
268268const malformedToolResult = {
269269role: "toolResult",
270270toolName: "read",
@@ -278,13 +278,13 @@ describe("pruneContextMessages", () => {
278278makeAssistant([{ type: "text", text: "done" }]),
279279];
280280281-expect(() =>
282-pruneContextMessages({
283- messages,
284- settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
285- ctx: CONTEXT_WINDOW_1M,
286- }),
287-).not.toThrow();
281+const result = pruneContextMessages({
282+messages,
283+settings: DEFAULT_CONTEXT_PRUNING_SETTINGS,
284+ctx: CONTEXT_WINDOW_1M,
285+});
286+287+expect(result).toHaveLength(3);
288288});
289289290290it("handles well-formed thinking blocks correctly", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。