mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:10:45 +00:00
test: share agent tool call id fixtures
This commit is contained in:
@@ -29,7 +29,35 @@ const buildDuplicateIdCollisionInput = () =>
|
||||
},
|
||||
]);
|
||||
|
||||
const buildRepeatedRawIdInput = () =>
|
||||
const readToolCall = (id: string) => ({
|
||||
type: "toolCall" as const,
|
||||
id,
|
||||
name: "read",
|
||||
arguments: {},
|
||||
});
|
||||
|
||||
const buildToolResult = (params: {
|
||||
toolCallId: string;
|
||||
text: string;
|
||||
toolName?: string;
|
||||
toolUseId?: string;
|
||||
}) => ({
|
||||
role: "toolResult" as const,
|
||||
toolCallId: params.toolCallId,
|
||||
...(params.toolUseId ? { toolUseId: params.toolUseId } : {}),
|
||||
toolName: params.toolName ?? "read",
|
||||
content: [{ type: "text" as const, text: params.text }],
|
||||
});
|
||||
|
||||
const signedReadAssistant = (signature: string, id: string) => ({
|
||||
role: "assistant" as const,
|
||||
content: [
|
||||
{ type: "thinking" as const, thinking: "internal", thinkingSignature: signature },
|
||||
readToolCall(id),
|
||||
],
|
||||
});
|
||||
|
||||
const buildRepeatedEditIdInput = (params: { includeToolUseId?: boolean } = {}) =>
|
||||
castAgentMessages([
|
||||
{
|
||||
role: "assistant",
|
||||
@@ -38,44 +66,24 @@ const buildRepeatedRawIdInput = () =>
|
||||
{ type: "toolCall", id: "edit:22", name: "edit", arguments: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
buildToolResult({
|
||||
toolCallId: "edit:22",
|
||||
toolName: "edit",
|
||||
content: [{ type: "text", text: "one" }],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
...(params.includeToolUseId ? { toolUseId: "edit:22" } : {}),
|
||||
text: "one",
|
||||
}),
|
||||
buildToolResult({
|
||||
toolCallId: "edit:22",
|
||||
toolName: "edit",
|
||||
content: [{ type: "text", text: "two" }],
|
||||
},
|
||||
...(params.includeToolUseId ? { toolUseId: "edit:22" } : {}),
|
||||
text: "two",
|
||||
}),
|
||||
]);
|
||||
|
||||
const buildRepeatedRawIdInput = () => buildRepeatedEditIdInput();
|
||||
|
||||
const buildRepeatedSharedToolResultIdInput = () =>
|
||||
castAgentMessages([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "toolCall", id: "edit:22", name: "edit", arguments: {} },
|
||||
{ type: "toolCall", id: "edit:22", name: "edit", arguments: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "edit:22",
|
||||
toolUseId: "edit:22",
|
||||
toolName: "edit",
|
||||
content: [{ type: "text", text: "one" }],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "edit:22",
|
||||
toolUseId: "edit:22",
|
||||
toolName: "edit",
|
||||
content: [{ type: "text", text: "two" }],
|
||||
},
|
||||
]);
|
||||
buildRepeatedEditIdInput({ includeToolUseId: true });
|
||||
|
||||
function expectCollisionIdsRemainDistinct(
|
||||
out: AgentMessage[],
|
||||
@@ -111,6 +119,29 @@ function expectSingleToolCallRewrite(
|
||||
expect(result.toolCallId).toBe(toolCall.id);
|
||||
}
|
||||
|
||||
function expectToolUseIdsFollowDistinctToolCallIds(
|
||||
out: AgentMessage[],
|
||||
mode: "strict" | "strict9",
|
||||
): { aId: string; bId: string } {
|
||||
const ids = expectCollisionIdsRemainDistinct(out, mode);
|
||||
const r1 = out[1] as Extract<AgentMessage, { role: "toolResult" }> & { toolUseId?: string };
|
||||
const r2 = out[2] as Extract<AgentMessage, { role: "toolResult" }> & { toolUseId?: string };
|
||||
expect(r1.toolUseId).toBe(ids.aId);
|
||||
expect(r2.toolUseId).toBe(ids.bId);
|
||||
return ids;
|
||||
}
|
||||
|
||||
function expectStrict9IdLengths(ids: { aId: string; bId: string }) {
|
||||
expect(ids.aId.length).toBe(9);
|
||||
expect(ids.bId.length).toBe(9);
|
||||
}
|
||||
|
||||
function expectDistinctStrict9Ids(out: AgentMessage[], input: AgentMessage[]) {
|
||||
expect(out).not.toBe(input);
|
||||
const ids = expectCollisionIdsRemainDistinct(out, "strict9");
|
||||
expectStrict9IdLengths(ids);
|
||||
}
|
||||
|
||||
function expectReplaySafeSignedTurnOwnership(params: {
|
||||
input: AgentMessage[];
|
||||
preservedTurn: "first" | "second";
|
||||
@@ -199,11 +230,7 @@ describe("sanitizeToolCallIdsForCloudCodeAssist", () => {
|
||||
|
||||
const out = sanitizeToolCallIdsForCloudCodeAssist(input);
|
||||
expect(out).not.toBe(input);
|
||||
const { aId, bId } = expectCollisionIdsRemainDistinct(out, "strict");
|
||||
const r1 = out[1] as Extract<AgentMessage, { role: "toolResult" }> & { toolUseId?: string };
|
||||
const r2 = out[2] as Extract<AgentMessage, { role: "toolResult" }> & { toolUseId?: string };
|
||||
expect(r1.toolUseId).toBe(aId);
|
||||
expect(r2.toolUseId).toBe(bId);
|
||||
expectToolUseIdsFollowDistinctToolCallIds(out, "strict");
|
||||
});
|
||||
|
||||
it("assigns distinct IDs when identical raw tool call ids repeat", () => {
|
||||
@@ -362,27 +389,11 @@ describe("sanitizeToolCallIdsForCloudCodeAssist", () => {
|
||||
const input = castAgentMessages([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [{ type: "toolCall", id: "call_1", name: "read", arguments: {} }],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "call_1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "first" }],
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "thinking", thinking: "internal", thinkingSignature: "sig_1" },
|
||||
{ type: "toolCall", id: "call1", name: "read", arguments: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "call1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "second" }],
|
||||
content: [readToolCall("call_1")],
|
||||
},
|
||||
buildToolResult({ toolCallId: "call_1", text: "first" }),
|
||||
signedReadAssistant("sig_1", "call1"),
|
||||
buildToolResult({ toolCallId: "call1", text: "second" }),
|
||||
]);
|
||||
|
||||
const out = sanitizeToolCallIdsForCloudCodeAssist(input, "strict", {
|
||||
@@ -404,32 +415,10 @@ describe("sanitizeToolCallIdsForCloudCodeAssist", () => {
|
||||
|
||||
it("rewrites later signed turns when an earlier signed turn already owns the raw id", () => {
|
||||
const input = castAgentMessages([
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "thinking", thinking: "internal", thinkingSignature: "sig_1" },
|
||||
{ type: "toolCall", id: "call1", name: "read", arguments: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "call1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "first" }],
|
||||
},
|
||||
{
|
||||
role: "assistant",
|
||||
content: [
|
||||
{ type: "thinking", thinking: "internal", thinkingSignature: "sig_2" },
|
||||
{ type: "toolCall", id: "call1", name: "read", arguments: {} },
|
||||
],
|
||||
},
|
||||
{
|
||||
role: "toolResult",
|
||||
toolCallId: "call1",
|
||||
toolName: "read",
|
||||
content: [{ type: "text", text: "second" }],
|
||||
},
|
||||
signedReadAssistant("sig_1", "call1"),
|
||||
buildToolResult({ toolCallId: "call1", text: "first" }),
|
||||
signedReadAssistant("sig_2", "call1"),
|
||||
buildToolResult({ toolCallId: "call1", text: "second" }),
|
||||
]);
|
||||
|
||||
expectReplaySafeSignedTurnOwnership({
|
||||
@@ -504,20 +493,14 @@ describe("sanitizeToolCallIdsForCloudCodeAssist", () => {
|
||||
]);
|
||||
|
||||
const out = sanitizeToolCallIdsForCloudCodeAssist(input, "strict9");
|
||||
expect(out).not.toBe(input);
|
||||
const { aId, bId } = expectCollisionIdsRemainDistinct(out, "strict9");
|
||||
expect(aId.length).toBe(9);
|
||||
expect(bId.length).toBe(9);
|
||||
expectDistinctStrict9Ids(out, input);
|
||||
});
|
||||
|
||||
it("assigns distinct strict9 IDs when identical raw tool call ids repeat", () => {
|
||||
const input = buildRepeatedRawIdInput();
|
||||
|
||||
const out = sanitizeToolCallIdsForCloudCodeAssist(input, "strict9");
|
||||
expect(out).not.toBe(input);
|
||||
const { aId, bId } = expectCollisionIdsRemainDistinct(out, "strict9");
|
||||
expect(aId.length).toBe(9);
|
||||
expect(bId.length).toBe(9);
|
||||
expectDistinctStrict9Ids(out, input);
|
||||
});
|
||||
|
||||
it("reuses one rewritten strict9 id when a tool result carries matching toolCallId and toolUseId", () => {
|
||||
@@ -525,11 +508,7 @@ describe("sanitizeToolCallIdsForCloudCodeAssist", () => {
|
||||
|
||||
const out = sanitizeToolCallIdsForCloudCodeAssist(input, "strict9");
|
||||
expect(out).not.toBe(input);
|
||||
const { aId, bId } = expectCollisionIdsRemainDistinct(out, "strict9");
|
||||
const r1 = out[1] as Extract<AgentMessage, { role: "toolResult" }> & { toolUseId?: string };
|
||||
const r2 = out[2] as Extract<AgentMessage, { role: "toolResult" }> & { toolUseId?: string };
|
||||
expect(r1.toolUseId).toBe(aId);
|
||||
expect(r2.toolUseId).toBe(bId);
|
||||
expectStrict9IdLengths(expectToolUseIdsFollowDistinctToolCallIds(out, "strict9"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user