chore(vendor): import pi 1.3.0

Imported as a linear vendor commit so forge rebases do not replay the upstream root tree.

git-subtree-dir: third_party/pi

git-subtree-split: 71023aec1546d6d677a65669c5665c0927ce0dd0
This commit is contained in:
2026-10-15 17:58:48 -04:00
parent 719370c8f7
commit 6081e3e325
1743 changed files with 205460 additions and 131705 deletions

View File

@@ -1,5 +1,5 @@
import type { AgentMessage } from "@earendil-works/pi-agent-core";
import type { AssistantMessage, Context, Model } from "@earendil-works/pi-ai";
import { type AssistantMessage, type Model, normalizeContext, type TranscriptContext } from "@earendil-works/pi-ai";
import { beforeEach, describe, expect, it, vi } from "vitest";
import {
type CompactionPreparation,
@@ -115,11 +115,11 @@ describe("generateSummary reasoning options", () => {
});
it("honors caller-supplied routing session and tool choice without prompt caching", async () => {
await completeSummarization(
createModel(false),
{ systemPrompt: "Summarize", messages: [] },
{ sessionId: "current-routing-session", cacheRetention: "long", toolChoice: "auto" },
);
await completeSummarization(createModel(false), normalizeContext({ systemPrompt: "Summarize", messages: [] }), {
sessionId: "current-routing-session",
cacheRetention: "long",
toolChoice: "auto",
});
expect(completeSimpleMock.mock.calls[0][2]).toMatchObject({
sessionId: "current-routing-session",
@@ -128,23 +128,27 @@ describe("generateSummary reasoning options", () => {
});
});
it("preserves the standalone split-turn summary prompt", async () => {
it("preserves the previous summary without an empty history request for a split turn", async () => {
const preparation: CompactionPreparation = {
firstKeptEntryId: "entry-keep",
messagesToSummarize: [],
turnPrefixMessages: messages,
isSplitTurn: true,
tokensBefore: 100,
previousSummary: "previous checkpoint",
fileOps: { read: new Set(), written: new Set(), edited: new Set() },
settings: { enabled: true, reserveTokens: 2000, keepRecentTokens: 20 },
};
await compact(preparation, createModel(false), "test-key");
const result = await compact(preparation, createModel(false), "test-key");
const requestContext = completeSimpleMock.mock.calls[0][1] as Context;
expect(completeSimpleMock).toHaveBeenCalledTimes(1);
expect(result.summary).toContain("previous checkpoint");
const requestContext = completeSimpleMock.mock.calls[0][1] as TranscriptContext;
const prompt = JSON.stringify(requestContext.messages);
expect(prompt).toContain("This is the PREFIX of a turn that was too large to keep");
expect(prompt).toContain("<conversation>");
// Regression test for #9652: clear boundaries and continuation wording avoid the reasoning-extraction false positive.
expect(prompt).toContain("# Conversation\\n[User]: Summarize this.");
expect(prompt).toContain("# Instructions\\nThe messages above are earlier context from an ongoing conversation.");
});
it("rejects tool calls from conversation summaries", async () => {