
















@@ -6,6 +6,28 @@ function makeModel(api: Api, provider: string, id: string): Model<Api> {
66return { api, provider, id, input: [], output: [] } as unknown as Model<Api>;
77}
889+type ToolResultMessage = Extract<Context["messages"][number], { role: "toolResult" }>;
10+11+function requireToolResultMessage(
12+message: Context["messages"][number] | undefined,
13+): ToolResultMessage {
14+if (!message || message.role !== "toolResult") {
15+throw new Error(`expected toolResult message, got ${message?.role ?? "missing"}`);
16+}
17+return message;
18+}
19+20+function toolResultSummaries(messages: Context["messages"]) {
21+return messages.map((message) => {
22+const toolResult = requireToolResultMessage(message);
23+return {
24+role: toolResult.role,
25+toolCallId: toolResult.toolCallId,
26+content: toolResult.content,
27+};
28+});
29+}
30+931function assistantToolCall(
1032id: string,
1133name = "read",
@@ -35,12 +57,10 @@ describe("transformTransportMessages synthetic tool-result policy", () => {
3557);
36583759expect(result.map((msg) => msg.role)).toEqual(["assistant", "toolResult", "user"]);
38-expect(result[1]).toMatchObject({
39-role: "toolResult",
40-toolCallId: "call_openai_1",
41-isError: true,
42-content: [{ type: "text", text: "aborted" }],
43-});
60+const toolResult = requireToolResultMessage(result[1]);
61+expect(toolResult.toolCallId).toBe("call_openai_1");
62+expect(toolResult.isError).toBe(true);
63+expect(toolResult.content).toEqual([{ type: "text", text: "aborted" }]);
4464});
45654666it("preserves real OpenAI transport results and aborts missing parallel siblings", () => {
@@ -74,7 +94,7 @@ describe("transformTransportMessages synthetic tool-result policy", () => {
7494"toolResult",
7595"user",
7696]);
77-expect(result.slice(1, 3)).toMatchObject([
97+expect(toolResultSummaries(result.slice(1, 3))).toEqual([
7898{ role: "toolResult", toolCallId: "call_keep", content: [{ type: "text", text: "ok" }] },
7999{
80100role: "toolResult",
@@ -115,7 +135,7 @@ describe("transformTransportMessages synthetic tool-result policy", () => {
115135"toolResult",
116136"user",
117137]);
118-expect(result.slice(1, 3)).toMatchObject([
138+expect(toolResultSummaries(result.slice(1, 3))).toEqual([
119139{ role: "toolResult", toolCallId: "call_keep", content: [{ type: "text", text: "late ok" }] },
120140{
121141role: "toolResult",
@@ -208,11 +228,9 @@ describe("transformTransportMessages synthetic tool-result policy", () => {
208228);
209229210230expect(result.map((msg) => msg.role)).toEqual(["assistant", "toolResult", "user"]);
211-expect(result[1]).toMatchObject({
212-role: "toolResult",
213-toolCallId: "call_anthropic_1",
214-isError: true,
215-});
231+const toolResult = requireToolResultMessage(result[1]);
232+expect(toolResult.toolCallId).toBe("call_anthropic_1");
233+expect(toolResult.isError).toBe(true);
216234});
217235218236it("still synthesizes missing tool results for transport alias apis that own replay repair", () => {
@@ -232,10 +250,8 @@ describe("transformTransportMessages synthetic tool-result policy", () => {
232250makeModel("openclaw-google-generative-ai-transport" as Api, "google", "gemini-2.5-pro"),
233251);
234252expect(googleAlias.map((msg) => msg.role)).toEqual(["assistant", "toolResult", "user"]);
235-expect(googleAlias[1]).toMatchObject({
236-role: "toolResult",
237-content: [{ type: "text", text: "No result provided" }],
238-});
253+const googleToolResult = requireToolResultMessage(googleAlias[1]);
254+expect(googleToolResult.content).toEqual([{ type: "text", text: "No result provided" }]);
239255240256const bedrockCanonical = transformTransportMessages(
241257messages,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。