mirror of
https://github.com/getpaseo/paseo.git
synced 2026-11-06 16:34:36 +00:00
fix: preserve inherited fork context and live history attachments
This commit is contained in:
@@ -572,3 +572,57 @@ it("preserves every message in fork history below the character budget", () => {
|
||||
`<chat-history-summary>\nChat history from a previous Paseo agent.\n\n[User] ${text}\n</chat-history-summary>`,
|
||||
);
|
||||
});
|
||||
|
||||
it.each(["", "Continue in B"])("carries inherited history through repeated forks (%s)", (text) => {
|
||||
const original = buildAgentForkContextAttachment({
|
||||
rows: [
|
||||
row(1, { type: "user_message", text: "Question in A" }),
|
||||
row(2, { type: "assistant_message", text: "Answer in A" }),
|
||||
],
|
||||
});
|
||||
const child = buildAgentForkContextAttachment({
|
||||
rows: [
|
||||
row(1, {
|
||||
type: "user_message",
|
||||
text,
|
||||
chatHistory: { ...original.attachment, contextKind: "chat_history" },
|
||||
}),
|
||||
row(2, { type: "assistant_message", text: "Answer in B" }),
|
||||
],
|
||||
});
|
||||
const grandchild = buildAgentForkContextAttachment({
|
||||
rows: [
|
||||
row(1, {
|
||||
type: "user_message",
|
||||
text: "Continue in C",
|
||||
chatHistory: { ...child.attachment, contextKind: "chat_history" },
|
||||
}),
|
||||
row(2, { type: "assistant_message", text: "Answer in C" }),
|
||||
],
|
||||
});
|
||||
expect(grandchild.attachment.text).toContain("[User] Question in A\n[Assistant] Answer in A");
|
||||
expect(grandchild.attachment.text).toContain("[Assistant] Answer in B");
|
||||
expect(grandchild.attachment.text).toContain("[User] Continue in C\n[Assistant] Answer in C");
|
||||
expect(grandchild.attachment.text.match(/<chat-history-summary>/g)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("keeps the fork budget when inherited history exceeds the remaining space", () => {
|
||||
const result = buildAgentForkContextAttachment({
|
||||
rows: [
|
||||
row(1, {
|
||||
type: "user_message",
|
||||
text: "Current question",
|
||||
chatHistory: {
|
||||
type: "text",
|
||||
mimeType: "text/plain",
|
||||
contextKind: "chat_history",
|
||||
text: "Old ".repeat(30_000),
|
||||
},
|
||||
}),
|
||||
row(2, { type: "assistant_message", text: "Latest answer" }),
|
||||
],
|
||||
});
|
||||
expect(result.attachment.text.length).toBeLessThanOrEqual(100_000);
|
||||
expect(result.attachment.text).toContain("[Earlier chat history omitted]");
|
||||
expect(result.attachment.text).toContain("[User] Current question\n[Assistant] Latest answer");
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { extractChatHistoryBody } from "@getpaseo/protocol/chat-history";
|
||||
import type { AgentTimelineItem } from "./agent-sdk-types.js";
|
||||
import type { AgentMessage } from "@getpaseo/protocol/agent-message";
|
||||
import type { AgentAttachment } from "@getpaseo/protocol/messages";
|
||||
@@ -21,6 +22,7 @@ const FORK_CONTEXT_KINDS: readonly AgentTimelineItem["type"][] = [
|
||||
];
|
||||
|
||||
interface ActivityCuratorOptions {
|
||||
includeChatHistory?: boolean;
|
||||
maxItems?: number;
|
||||
labelAssistantMessages?: boolean;
|
||||
includeKinds?: readonly AgentTimelineItem["type"][];
|
||||
@@ -37,6 +39,17 @@ function activityEntry(text: string): ActivityEntry {
|
||||
return { text };
|
||||
}
|
||||
|
||||
function appendUserEntry(
|
||||
entries: ActivityEntry[],
|
||||
item: Extract<AgentTimelineItem, { type: "user_message" }>,
|
||||
options?: ActivityCuratorOptions,
|
||||
) {
|
||||
if (options?.includeChatHistory && item.chatHistory) {
|
||||
entries.push(activityEntry(extractChatHistoryBody(item.chatHistory.text)));
|
||||
}
|
||||
entries.push(activityEntry(`[User] ${item.text.trim()}`));
|
||||
}
|
||||
|
||||
function appendTextEntry(
|
||||
entries: ActivityEntry[],
|
||||
item: Extract<AgentTimelineItem, { type: "assistant_message" | "reasoning" }>,
|
||||
@@ -158,7 +171,7 @@ function curateProjectedActivityEntries(
|
||||
|
||||
switch (item.type) {
|
||||
case "user_message":
|
||||
entries.push(activityEntry(`[User] ${item.text.trim()}`));
|
||||
appendUserEntry(entries, item, options);
|
||||
break;
|
||||
case "assistant_message":
|
||||
case "reasoning":
|
||||
@@ -361,6 +374,7 @@ export function buildAgentForkContextAttachment(input: {
|
||||
});
|
||||
const entries = curateProjectedActivityEntries(selected.items, {
|
||||
maxItems: 0,
|
||||
includeChatHistory: true,
|
||||
labelAssistantMessages: true,
|
||||
includeKinds: FORK_CONTEXT_KINDS,
|
||||
includeExternalToolInput: false,
|
||||
|
||||
Reference in New Issue
Block a user