fix(agent): preserved clamped tool image results
Added a textual omission marker when provider image clamping removes every block from a successful tool result, keeping the serialized tool_result meaningful and protocol-safe.\n\nFixes #3230
This commit is contained in:
@@ -9,6 +9,11 @@ import type {
|
||||
} from "@oh-my-pi/pi-ai";
|
||||
import { providerImageBudget } from "@oh-my-pi/snapcompact";
|
||||
|
||||
const TOOL_RESULT_IMAGE_OMISSION: TextContent = {
|
||||
type: "text",
|
||||
text: "[image omitted: provider image limit]",
|
||||
};
|
||||
|
||||
function countImages(context: Context): number {
|
||||
let count = 0;
|
||||
for (const message of context.messages) {
|
||||
@@ -52,7 +57,8 @@ function clampDeveloperMessage(message: DeveloperMessage, state: { remainingDrop
|
||||
function clampToolResultMessage(message: ToolResultMessage, state: { remainingDrops: number }): ToolResultMessage {
|
||||
if (state.remainingDrops <= 0) return message;
|
||||
const content = clampContent(message.content, state);
|
||||
return content ? { ...message, content } : message;
|
||||
if (!content) return message;
|
||||
return { ...message, content: content.length > 0 ? content : [TOOL_RESULT_IMAGE_OMISSION] };
|
||||
}
|
||||
|
||||
/** Drops oldest transient image blocks so outgoing vision requests fit the active provider's image cap. */
|
||||
|
||||
@@ -69,6 +69,28 @@ describe("provider context image budgets", () => {
|
||||
expect(imageData(context)).toEqual(Array.from({ length: 31 }, (_, index) => `image-${index}`));
|
||||
});
|
||||
|
||||
it("keeps image-only tool results meaningful when every image block is dropped", () => {
|
||||
const context: Context = {
|
||||
systemPrompt: [],
|
||||
tools: [],
|
||||
messages: Array.from({ length: 11 }, (_, index) => ({
|
||||
role: "toolResult",
|
||||
toolCallId: `call-${index}`,
|
||||
toolName: "inspect_image",
|
||||
content: [image(`image-${index}`)],
|
||||
isError: false,
|
||||
timestamp: index,
|
||||
})),
|
||||
};
|
||||
|
||||
const clamped = clampProviderContextImages(context, UMANS_MODEL);
|
||||
const firstMessage = clamped.messages[0];
|
||||
|
||||
expect(imageData(clamped)).toEqual(Array.from({ length: 10 }, (_, index) => `image-${index + 1}`));
|
||||
expect(firstMessage?.role).toBe("toolResult");
|
||||
expect(firstMessage?.content).toEqual([text("[image omitted: provider image limit]")]);
|
||||
});
|
||||
|
||||
it("preserves context identity when the provider cap is not exceeded", () => {
|
||||
const context: Context = {
|
||||
systemPrompt: [],
|
||||
|
||||
Reference in New Issue
Block a user