mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-02 17:00:22 +00:00
refactor: dedupe test and script helpers
This commit is contained in:
@@ -13,6 +13,10 @@ import {
|
||||
} from "./attempt.spawn-workspace.test-support.js";
|
||||
|
||||
const hoisted = getHoisted();
|
||||
const embeddedSessionId = "embedded-session";
|
||||
const sessionFile = "/tmp/session.jsonl";
|
||||
const seedMessage = { role: "user", content: "seed", timestamp: 1 } as AgentMessage;
|
||||
const doneMessage = { role: "assistant", content: "done", timestamp: 2 } as unknown as AgentMessage;
|
||||
|
||||
function createTestContextEngine(params: Partial<AttemptContextEngine>): AttemptContextEngine {
|
||||
return {
|
||||
@@ -31,6 +35,65 @@ function createTestContextEngine(params: Partial<AttemptContextEngine>): Attempt
|
||||
} as AttemptContextEngine;
|
||||
}
|
||||
|
||||
async function runBootstrap(
|
||||
sessionKey: string,
|
||||
contextEngine: AttemptContextEngine,
|
||||
overrides: Partial<Parameters<typeof runAttemptContextEngineBootstrap>[0]> = {},
|
||||
) {
|
||||
await runAttemptContextEngineBootstrap({
|
||||
hadSessionFile: true,
|
||||
contextEngine,
|
||||
sessionId: embeddedSessionId,
|
||||
sessionKey,
|
||||
sessionFile,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
warn: () => {},
|
||||
...overrides,
|
||||
});
|
||||
}
|
||||
|
||||
async function runAssemble(
|
||||
sessionKey: string,
|
||||
contextEngine: AttemptContextEngine,
|
||||
overrides: Partial<Parameters<typeof assembleAttemptContextEngine>[0]> = {},
|
||||
) {
|
||||
await assembleAttemptContextEngine({
|
||||
contextEngine,
|
||||
sessionId: embeddedSessionId,
|
||||
sessionKey,
|
||||
messages: [seedMessage],
|
||||
tokenBudget: 2048,
|
||||
modelId: "gpt-test",
|
||||
...overrides,
|
||||
});
|
||||
}
|
||||
|
||||
async function finalizeTurn(
|
||||
sessionKey: string,
|
||||
contextEngine: AttemptContextEngine,
|
||||
overrides: Partial<Parameters<typeof finalizeAttemptContextEngineTurn>[0]> = {},
|
||||
) {
|
||||
await finalizeAttemptContextEngineTurn({
|
||||
contextEngine,
|
||||
promptError: false,
|
||||
aborted: false,
|
||||
yieldAborted: false,
|
||||
sessionIdUsed: embeddedSessionId,
|
||||
sessionKey,
|
||||
sessionFile,
|
||||
messagesSnapshot: [doneMessage],
|
||||
prePromptMessageCount: 0,
|
||||
tokenBudget: 2048,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
warn: () => {},
|
||||
...overrides,
|
||||
});
|
||||
}
|
||||
|
||||
describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
const sessionKey = "agent:main:discord:channel:test-ctx-engine";
|
||||
|
||||
@@ -47,43 +110,9 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
afterTurn,
|
||||
});
|
||||
|
||||
await runAttemptContextEngineBootstrap({
|
||||
hadSessionFile: true,
|
||||
contextEngine,
|
||||
sessionId: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
sessionManager: hoisted.sessionManager,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
warn: () => {},
|
||||
});
|
||||
await assembleAttemptContextEngine({
|
||||
contextEngine,
|
||||
sessionId: "embedded-session",
|
||||
sessionKey,
|
||||
messages: [{ role: "user", content: "seed", timestamp: 1 } as AgentMessage],
|
||||
tokenBudget: 2048,
|
||||
modelId: "gpt-test",
|
||||
});
|
||||
await finalizeAttemptContextEngineTurn({
|
||||
contextEngine,
|
||||
promptError: false,
|
||||
aborted: false,
|
||||
yieldAborted: false,
|
||||
sessionIdUsed: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
messagesSnapshot: [
|
||||
{ role: "assistant", content: "done", timestamp: 2 } as unknown as AgentMessage,
|
||||
],
|
||||
prePromptMessageCount: 0,
|
||||
tokenBudget: 2048,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
warn: () => {},
|
||||
});
|
||||
await runBootstrap(sessionKey, contextEngine);
|
||||
await runAssemble(sessionKey, contextEngine);
|
||||
await finalizeTurn(sessionKey, contextEngine);
|
||||
|
||||
expectCalledWithSessionKey(bootstrap, sessionKey);
|
||||
expectCalledWithSessionKey(assemble, sessionKey);
|
||||
@@ -94,25 +123,8 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
const { bootstrap, assemble } = createContextEngineBootstrapAndAssemble();
|
||||
const contextEngine = createTestContextEngine({ bootstrap, assemble });
|
||||
|
||||
await runAttemptContextEngineBootstrap({
|
||||
hadSessionFile: true,
|
||||
contextEngine,
|
||||
sessionId: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
sessionManager: hoisted.sessionManager,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
warn: () => {},
|
||||
});
|
||||
await assembleAttemptContextEngine({
|
||||
contextEngine,
|
||||
sessionId: "embedded-session",
|
||||
sessionKey,
|
||||
messages: [{ role: "user", content: "seed", timestamp: 1 } as AgentMessage],
|
||||
tokenBudget: 2048,
|
||||
modelId: "gpt-test",
|
||||
});
|
||||
await runBootstrap(sessionKey, contextEngine);
|
||||
await runAssemble(sessionKey, contextEngine);
|
||||
|
||||
expect(assemble).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -127,28 +139,9 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
async (_params: { sessionKey?: string; messages: AgentMessage[] }) => ({ ingestedCount: 1 }),
|
||||
);
|
||||
|
||||
await finalizeAttemptContextEngineTurn({
|
||||
contextEngine: createTestContextEngine({
|
||||
bootstrap,
|
||||
assemble,
|
||||
ingestBatch,
|
||||
}),
|
||||
promptError: false,
|
||||
aborted: false,
|
||||
yieldAborted: false,
|
||||
sessionIdUsed: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
messagesSnapshot: [
|
||||
{ role: "user", content: "seed", timestamp: 1 } as AgentMessage,
|
||||
{ role: "assistant", content: "done", timestamp: 2 } as unknown as AgentMessage,
|
||||
],
|
||||
await finalizeTurn(sessionKey, createTestContextEngine({ bootstrap, assemble, ingestBatch }), {
|
||||
messagesSnapshot: [seedMessage, doneMessage],
|
||||
prePromptMessageCount: 1,
|
||||
tokenBudget: 2048,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
warn: () => {},
|
||||
});
|
||||
|
||||
expectCalledWithSessionKey(ingestBatch, sessionKey);
|
||||
@@ -160,28 +153,9 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
ingested: true,
|
||||
}));
|
||||
|
||||
await finalizeAttemptContextEngineTurn({
|
||||
contextEngine: createTestContextEngine({
|
||||
bootstrap,
|
||||
assemble,
|
||||
ingest,
|
||||
}),
|
||||
promptError: false,
|
||||
aborted: false,
|
||||
yieldAborted: false,
|
||||
sessionIdUsed: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
messagesSnapshot: [
|
||||
{ role: "user", content: "seed", timestamp: 1 } as AgentMessage,
|
||||
{ role: "assistant", content: "done", timestamp: 2 } as unknown as AgentMessage,
|
||||
],
|
||||
await finalizeTurn(sessionKey, createTestContextEngine({ bootstrap, assemble, ingest }), {
|
||||
messagesSnapshot: [seedMessage, doneMessage],
|
||||
prePromptMessageCount: 1,
|
||||
tokenBudget: 2048,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
warn: () => {},
|
||||
});
|
||||
|
||||
expect(ingest).toHaveBeenCalled();
|
||||
@@ -199,28 +173,7 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
throw new Error("afterTurn failed");
|
||||
});
|
||||
|
||||
await finalizeAttemptContextEngineTurn({
|
||||
contextEngine: createTestContextEngine({
|
||||
bootstrap,
|
||||
assemble,
|
||||
afterTurn,
|
||||
}),
|
||||
promptError: false,
|
||||
aborted: false,
|
||||
yieldAborted: false,
|
||||
sessionIdUsed: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
messagesSnapshot: [
|
||||
{ role: "assistant", content: "done", timestamp: 2 } as unknown as AgentMessage,
|
||||
],
|
||||
prePromptMessageCount: 0,
|
||||
tokenBudget: 2048,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
warn: () => {},
|
||||
});
|
||||
await finalizeTurn(sessionKey, createTestContextEngine({ bootstrap, assemble, afterTurn }));
|
||||
|
||||
expect(afterTurn).toHaveBeenCalled();
|
||||
expect(hoisted.runContextEngineMaintenanceMock).not.toHaveBeenCalledWith(
|
||||
@@ -231,9 +184,9 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
it("runs startup maintenance for existing sessions even without bootstrap()", async () => {
|
||||
const { assemble } = createContextEngineBootstrapAndAssemble();
|
||||
|
||||
await runAttemptContextEngineBootstrap({
|
||||
hadSessionFile: true,
|
||||
contextEngine: createTestContextEngine({
|
||||
await runBootstrap(
|
||||
sessionKey,
|
||||
createTestContextEngine({
|
||||
assemble,
|
||||
maintain: async () => ({
|
||||
changed: false,
|
||||
@@ -242,14 +195,7 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
reason: "test maintenance",
|
||||
}),
|
||||
}),
|
||||
sessionId: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
sessionManager: hoisted.sessionManager,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
warn: () => {},
|
||||
});
|
||||
);
|
||||
|
||||
expect(hoisted.runContextEngineMaintenanceMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ reason: "bootstrap" }),
|
||||
@@ -262,28 +208,9 @@ describe("runEmbeddedAttempt context engine sessionKey forwarding", () => {
|
||||
throw new Error("ingestBatch failed");
|
||||
});
|
||||
|
||||
await finalizeAttemptContextEngineTurn({
|
||||
contextEngine: createTestContextEngine({
|
||||
bootstrap,
|
||||
assemble,
|
||||
ingestBatch,
|
||||
}),
|
||||
promptError: false,
|
||||
aborted: false,
|
||||
yieldAborted: false,
|
||||
sessionIdUsed: "embedded-session",
|
||||
sessionKey,
|
||||
sessionFile: "/tmp/session.jsonl",
|
||||
messagesSnapshot: [
|
||||
{ role: "user", content: "seed", timestamp: 1 } as AgentMessage,
|
||||
{ role: "assistant", content: "done", timestamp: 2 } as unknown as AgentMessage,
|
||||
],
|
||||
await finalizeTurn(sessionKey, createTestContextEngine({ bootstrap, assemble, ingestBatch }), {
|
||||
messagesSnapshot: [seedMessage, doneMessage],
|
||||
prePromptMessageCount: 1,
|
||||
tokenBudget: 2048,
|
||||
runtimeContext: {},
|
||||
runMaintenance: hoisted.runContextEngineMaintenanceMock,
|
||||
sessionManager: hoisted.sessionManager,
|
||||
warn: () => {},
|
||||
});
|
||||
|
||||
expect(ingestBatch).toHaveBeenCalled();
|
||||
|
||||
@@ -40,6 +40,102 @@ function getBranchMessages(sessionManager: SessionManager): AgentMessage[] {
|
||||
.map((entry) => entry.message);
|
||||
}
|
||||
|
||||
function appendSessionMessages(
|
||||
sessionManager: SessionManager,
|
||||
messages: AppendMessage[],
|
||||
): string[] {
|
||||
return messages.map((message) => sessionManager.appendMessage(message));
|
||||
}
|
||||
|
||||
function createTextContent(text: string) {
|
||||
return [{ type: "text", text }];
|
||||
}
|
||||
|
||||
function createReadRewriteSession(options?: { tailAssistantText?: string }) {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
const entryIds = appendSessionMessages(sessionManager, [
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "read file",
|
||||
timestamp: 1,
|
||||
}),
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "toolCall", id: "call_1", name: "read", arguments: {} }],
|
||||
timestamp: 2,
|
||||
}),
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: createTextContent("x".repeat(8_000)),
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
}),
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: createTextContent(options?.tailAssistantText ?? "summarized"),
|
||||
timestamp: 4,
|
||||
}),
|
||||
]);
|
||||
return {
|
||||
sessionManager,
|
||||
toolResultEntryId: entryIds[2],
|
||||
tailAssistantEntryId: entryIds[3],
|
||||
};
|
||||
}
|
||||
|
||||
function createExecRewriteSession() {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
const entryIds = appendSessionMessages(sessionManager, [
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "run tool",
|
||||
timestamp: 1,
|
||||
}),
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "exec",
|
||||
content: createTextContent("before rewrite"),
|
||||
isError: false,
|
||||
timestamp: 2,
|
||||
}),
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: createTextContent("summarized"),
|
||||
timestamp: 3,
|
||||
}),
|
||||
]);
|
||||
return {
|
||||
sessionManager,
|
||||
toolResultEntryId: entryIds[1],
|
||||
};
|
||||
}
|
||||
|
||||
function createToolResultReplacement(toolName: string, text: string, timestamp: number) {
|
||||
return {
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName,
|
||||
content: createTextContent(text),
|
||||
isError: false,
|
||||
timestamp,
|
||||
} as AgentMessage;
|
||||
}
|
||||
|
||||
function findAssistantEntryByText(sessionManager: SessionManager, text: string) {
|
||||
return sessionManager
|
||||
.getBranch()
|
||||
.find(
|
||||
(entry) =>
|
||||
entry.type === "message" &&
|
||||
entry.message.role === "assistant" &&
|
||||
Array.isArray(entry.message.content) &&
|
||||
entry.message.content.some((part) => part.type === "text" && part.text === text),
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(async () => {
|
||||
acquireSessionWriteLockMock.mockClear();
|
||||
acquireSessionWriteLockReleaseMock.mockClear();
|
||||
@@ -48,57 +144,14 @@ beforeEach(async () => {
|
||||
|
||||
describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
it("branches from the first replaced message and re-appends the remaining suffix", () => {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "read file",
|
||||
timestamp: 1,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "toolCall", id: "call_1", name: "read", arguments: {} }],
|
||||
timestamp: 2,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "x".repeat(8_000) }],
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "summarized" }],
|
||||
timestamp: 4,
|
||||
}),
|
||||
);
|
||||
|
||||
const toolResultEntry = sessionManager
|
||||
.getBranch()
|
||||
.find((entry) => entry.type === "message" && entry.message.role === "toolResult");
|
||||
expect(toolResultEntry).toBeDefined();
|
||||
const { sessionManager, toolResultEntryId } = createReadRewriteSession();
|
||||
|
||||
const result = rewriteTranscriptEntriesInSessionManager({
|
||||
sessionManager,
|
||||
replacements: [
|
||||
{
|
||||
entryId: toolResultEntry!.id,
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "[externalized file_123]" }],
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
},
|
||||
entryId: toolResultEntryId,
|
||||
message: createToolResultReplacement("read", "[externalized file_123]", 3),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -123,48 +176,8 @@ describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
});
|
||||
|
||||
it("preserves active-branch labels after rewritten entries are re-appended", () => {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "read file",
|
||||
timestamp: 1,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "toolCall", id: "call_1", name: "read", arguments: {} }],
|
||||
timestamp: 2,
|
||||
}),
|
||||
);
|
||||
const toolResultEntryId = sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "x".repeat(8_000) }],
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "summarized" }],
|
||||
timestamp: 4,
|
||||
}),
|
||||
);
|
||||
|
||||
const summaryEntry = sessionManager
|
||||
.getBranch()
|
||||
.find(
|
||||
(entry) =>
|
||||
entry.type === "message" &&
|
||||
entry.message.role === "assistant" &&
|
||||
Array.isArray(entry.message.content) &&
|
||||
entry.message.content.some((part) => part.type === "text" && part.text === "summarized"),
|
||||
);
|
||||
const { sessionManager, toolResultEntryId } = createReadRewriteSession();
|
||||
const summaryEntry = findAssistantEntryByText(sessionManager, "summarized");
|
||||
expect(summaryEntry).toBeDefined();
|
||||
sessionManager.appendLabelChange(summaryEntry!.id, "bookmark");
|
||||
|
||||
@@ -173,66 +186,24 @@ describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
replacements: [
|
||||
{
|
||||
entryId: toolResultEntryId,
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "[externalized file_123]" }],
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
},
|
||||
message: createToolResultReplacement("read", "[externalized file_123]", 3),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(result.changed).toBe(true);
|
||||
const rewrittenSummaryEntry = sessionManager
|
||||
.getBranch()
|
||||
.find(
|
||||
(entry) =>
|
||||
entry.type === "message" &&
|
||||
entry.message.role === "assistant" &&
|
||||
Array.isArray(entry.message.content) &&
|
||||
entry.message.content.some((part) => part.type === "text" && part.text === "summarized"),
|
||||
);
|
||||
const rewrittenSummaryEntry = findAssistantEntryByText(sessionManager, "summarized");
|
||||
expect(rewrittenSummaryEntry).toBeDefined();
|
||||
expect(sessionManager.getLabel(rewrittenSummaryEntry!.id)).toBe("bookmark");
|
||||
expect(sessionManager.getBranch().some((entry) => entry.type === "label")).toBe(true);
|
||||
});
|
||||
|
||||
it("remaps compaction keep markers when rewritten entries change ids", () => {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "read file",
|
||||
timestamp: 1,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "toolCall", id: "call_1", name: "read", arguments: {} }],
|
||||
timestamp: 2,
|
||||
}),
|
||||
);
|
||||
const toolResultEntryId = sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "x".repeat(8_000) }],
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
}),
|
||||
);
|
||||
const keptAssistantEntryId = sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "keep me" }],
|
||||
timestamp: 4,
|
||||
}),
|
||||
);
|
||||
const {
|
||||
sessionManager,
|
||||
toolResultEntryId,
|
||||
tailAssistantEntryId: keptAssistantEntryId,
|
||||
} = createReadRewriteSession({ tailAssistantText: "keep me" });
|
||||
sessionManager.appendCompaction("summary", keptAssistantEntryId, 123);
|
||||
|
||||
const result = rewriteTranscriptEntriesInSessionManager({
|
||||
@@ -240,14 +211,7 @@ describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
replacements: [
|
||||
{
|
||||
entryId: toolResultEntryId,
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "[externalized file_123]" }],
|
||||
isError: false,
|
||||
timestamp: 3,
|
||||
},
|
||||
message: createToolResultReplacement("read", "[externalized file_123]", 3),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -270,31 +234,7 @@ describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
});
|
||||
|
||||
it("bypasses persistence hooks when replaying rewritten messages", () => {
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "run tool",
|
||||
timestamp: 1,
|
||||
}),
|
||||
);
|
||||
const toolResultEntryId = sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "exec",
|
||||
content: [{ type: "text", text: "before rewrite" }],
|
||||
isError: false,
|
||||
timestamp: 2,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "summarized" }],
|
||||
timestamp: 3,
|
||||
}),
|
||||
);
|
||||
const { sessionManager, toolResultEntryId } = createExecRewriteSession();
|
||||
installSessionToolResultGuard(sessionManager, {
|
||||
transformToolResultForPersistence: (message) => ({
|
||||
...(message as Extract<AgentMessage, { role: "toolResult" }>),
|
||||
@@ -309,14 +249,7 @@ describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
replacements: [
|
||||
{
|
||||
entryId: toolResultEntryId,
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "exec",
|
||||
content: [{ type: "text", text: "[exact replacement]" }],
|
||||
isError: false,
|
||||
timestamp: 2,
|
||||
},
|
||||
message: createToolResultReplacement("exec", "[exact replacement]", 2),
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -341,29 +274,7 @@ describe("rewriteTranscriptEntriesInSessionManager", () => {
|
||||
describe("rewriteTranscriptEntriesInSessionFile", () => {
|
||||
it("emits transcript updates when the active branch changes", async () => {
|
||||
const sessionFile = "/tmp/session.jsonl";
|
||||
const sessionManager = SessionManager.inMemory();
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "user",
|
||||
content: "run tool",
|
||||
timestamp: 1,
|
||||
}),
|
||||
);
|
||||
sessionManager.appendMessage(
|
||||
asAppendMessage({
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "exec",
|
||||
content: [{ type: "text", text: "y".repeat(6_000) }],
|
||||
isError: false,
|
||||
timestamp: 2,
|
||||
}),
|
||||
);
|
||||
|
||||
const toolResultEntry = sessionManager
|
||||
.getBranch()
|
||||
.find((entry) => entry.type === "message" && entry.message.role === "toolResult");
|
||||
expect(toolResultEntry).toBeDefined();
|
||||
const { sessionManager, toolResultEntryId } = createExecRewriteSession();
|
||||
|
||||
const openSpy = vi
|
||||
.spyOn(SessionManager, "open")
|
||||
@@ -378,15 +289,8 @@ describe("rewriteTranscriptEntriesInSessionFile", () => {
|
||||
request: {
|
||||
replacements: [
|
||||
{
|
||||
entryId: toolResultEntry!.id,
|
||||
message: {
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "exec",
|
||||
content: [{ type: "text", text: "[file_ref:file_abc]" }],
|
||||
isError: false,
|
||||
timestamp: 2,
|
||||
},
|
||||
entryId: toolResultEntryId,
|
||||
message: createToolResultReplacement("exec", "[file_ref:file_abc]", 2),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user