UNPKG

@copilotkit/runtime-client-gql

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

1,106 lines (1,105 loc) • 38.9 kB
import { aguiMessageWithImageToGQLMessage, aguiMessageWithRenderToGQL, aguiTextMessageToGQLMessage, aguiToGQL, aguiToolCallToGQLActionExecution, aguiToolMessageToGQLResultMessage } from "../chunk-SCACOKQX.mjs"; import { describe, globalExpect, test, vi } from "../chunk-2R7M2FWR.mjs"; import "../chunk-7ECCT6PK.mjs"; import "../chunk-FXYV7IUL.mjs"; import "../chunk-X2UAP3QY.mjs"; import "../chunk-HEODM5TW.mjs"; import "../chunk-4KTMZMM2.mjs"; import "../chunk-P2AUSQOK.mjs"; import { ActionExecutionMessage, AgentStateMessage, ImageMessage, ResultMessage, Role, TextMessage } from "../chunk-ROUIRR4B.mjs"; import "../chunk-WM3ARNBD.mjs"; import "../chunk-DELDZXUX.mjs"; // src/message-conversion/agui-to-gql.test.ts describe("agui-to-gql", () => { describe("aguiTextMessageToGQLMessage", () => { test("should convert developer message", () => { const aguiMessage = { id: "dev-message-id", role: "developer", content: "Hello from developer" }; const result = aguiTextMessageToGQLMessage(aguiMessage); globalExpect(result).toBeInstanceOf(TextMessage); globalExpect(result.id).toBe("dev-message-id"); globalExpect(result.content).toBe("Hello from developer"); globalExpect(result.role).toBe(Role.Developer); }); test("should convert system message", () => { const aguiMessage = { id: "system-message-id", role: "system", content: "System instruction" }; const result = aguiTextMessageToGQLMessage(aguiMessage); globalExpect(result).toBeInstanceOf(TextMessage); globalExpect(result.id).toBe("system-message-id"); globalExpect(result.content).toBe("System instruction"); globalExpect(result.role).toBe(Role.System); }); test("should convert assistant message", () => { const aguiMessage = { id: "assistant-message-id", role: "assistant", content: "Assistant response" }; const result = aguiTextMessageToGQLMessage(aguiMessage); globalExpect(result).toBeInstanceOf(TextMessage); globalExpect(result.id).toBe("assistant-message-id"); globalExpect(result.content).toBe("Assistant response"); globalExpect(result.role).toBe(Role.Assistant); }); test("should convert user message", () => { const aguiMessage = { id: "user-message-id", role: "user", content: "User input" }; const result = aguiTextMessageToGQLMessage(aguiMessage); globalExpect(result).toBeInstanceOf(TextMessage); globalExpect(result.id).toBe("user-message-id"); globalExpect(result.content).toBe("User input"); globalExpect(result.role).toBe(Role.User); }); test("should throw error for unsupported role", () => { const aguiMessage = { id: "tool-message-id", role: "tool", content: "Tool response", toolCallId: "tool-call-id" }; globalExpect(() => aguiTextMessageToGQLMessage(aguiMessage)).toThrow( "Cannot convert message with role tool to TextMessage" ); }); test("should handle undefined content", () => { const aguiMessage = { id: "assistant-message-id", role: "assistant", content: void 0 }; const result = aguiTextMessageToGQLMessage(aguiMessage); globalExpect(result.content).toBe(""); }); }); describe("aguiToolCallToGQLActionExecution", () => { test("should convert function tool call to action execution message", () => { const toolCall = { id: "tool-call-id", type: "function", function: { name: "testFunction", arguments: JSON.stringify({ param: "value" }) } }; const result = aguiToolCallToGQLActionExecution(toolCall, "parent-message-id"); globalExpect(result).toBeInstanceOf(ActionExecutionMessage); globalExpect(result.id).toBe("tool-call-id"); globalExpect(result.name).toBe("testFunction"); globalExpect(result.arguments).toEqual({ param: "value" }); globalExpect(result.parentMessageId).toBe("parent-message-id"); }); test("should throw error for unsupported tool call type", () => { const toolCall = { id: "tool-call-id", type: "unsupported-type", function: { name: "testFunction", arguments: "{}" } }; globalExpect(() => aguiToolCallToGQLActionExecution(toolCall, "parent-id")).toThrow( "Unsupported tool call type" ); }); }); describe("aguiToolMessageToGQLResultMessage", () => { test("should convert tool message to result message", () => { const aguiMessage = { id: "tool-message-id", role: "tool", content: "Tool execution result", toolCallId: "tool-call-id" }; const toolCallNames = { "tool-call-id": "testFunction" }; const result = aguiToolMessageToGQLResultMessage(aguiMessage, toolCallNames); globalExpect(result).toBeInstanceOf(ResultMessage); globalExpect(result.id).toBe("tool-message-id"); globalExpect(result.result).toBe("Tool execution result"); globalExpect(result.actionExecutionId).toBe("tool-call-id"); globalExpect(result.actionName).toBe("testFunction"); }); test("should throw error for non-tool message", () => { const aguiMessage = { id: "assistant-message-id", role: "assistant", content: "Assistant response" }; globalExpect(() => aguiToolMessageToGQLResultMessage(aguiMessage, {})).toThrow( "Cannot convert message with role assistant to ResultMessage" ); }); test("should throw error for tool message without toolCallId", () => { const aguiMessage = { id: "tool-message-id", role: "tool", content: "Tool execution result" }; globalExpect(() => aguiToolMessageToGQLResultMessage(aguiMessage, {})).toThrow( "Tool message must have a toolCallId" ); }); test("should handle undefined content", () => { const aguiMessage = { id: "tool-message-id", role: "tool", content: void 0, toolCallId: "tool-call-id" }; const toolCallNames = { "tool-call-id": "testFunction" }; const result = aguiToolMessageToGQLResultMessage(aguiMessage, toolCallNames); globalExpect(result.result).toBe(""); globalExpect(result.actionName).toBe("testFunction"); }); }); describe("aguiToGQL", () => { test("should convert an array of text messages", () => { const aguiMessages = [ { id: "dev-1", role: "developer", content: "Hello" }, { id: "assistant-1", role: "assistant", content: "Hi there" } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].id).toBe("dev-1"); globalExpect(result[0].content).toBe("Hello"); globalExpect(result[0].role).toBe(Role.Developer); globalExpect(result[1]).toBeInstanceOf(TextMessage); globalExpect(result[1].id).toBe("assistant-1"); globalExpect(result[1].content).toBe("Hi there"); globalExpect(result[1].role).toBe(Role.Assistant); }); test("should convert an array of text messages including user messages", () => { const aguiMessages = [ { id: "user-1", role: "user", content: "Hello from user" }, { id: "assistant-1", role: "assistant", content: "Hi there" }, { id: "user-2", role: "user", content: "Another user message" } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(3); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].id).toBe("user-1"); globalExpect(result[0].content).toBe("Hello from user"); globalExpect(result[0].role).toBe(Role.User); globalExpect(result[1]).toBeInstanceOf(TextMessage); globalExpect(result[1].id).toBe("assistant-1"); globalExpect(result[1].content).toBe("Hi there"); globalExpect(result[1].role).toBe(Role.Assistant); globalExpect(result[2]).toBeInstanceOf(TextMessage); globalExpect(result[2].id).toBe("user-2"); globalExpect(result[2].content).toBe("Another user message"); globalExpect(result[2].role).toBe(Role.User); }); test("should handle assistant messages with tool calls", () => { const aguiMessages = [ { id: "assistant-1", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "testFunction", arguments: JSON.stringify({ param: "value" }) } } ] } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].id).toBe("assistant-1"); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[1].id).toBe("tool-call-1"); globalExpect(result[1].name).toBe("testFunction"); globalExpect(result[1].arguments).toEqual({ param: "value" }); globalExpect(result[1].parentMessageId).toBe("assistant-1"); }); test("should handle multiple tool calls in assistant message", () => { const aguiMessages = [ { id: "assistant-1", role: "assistant", content: "I'll execute multiple functions", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "firstFunction", arguments: JSON.stringify({ param: "value1" }) } }, { id: "tool-call-2", type: "function", function: { name: "secondFunction", arguments: JSON.stringify({ param: "value2" }) } } ] } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(3); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[1].id).toBe("tool-call-1"); globalExpect(result[1].name).toBe("firstFunction"); globalExpect(result[2]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[2].id).toBe("tool-call-2"); globalExpect(result[2].name).toBe("secondFunction"); }); test("should convert tool messages to result messages", () => { const aguiMessages = [ { id: "tool-1", role: "tool", content: "Tool result", toolCallId: "tool-call-1" } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(ResultMessage); globalExpect(result[0].id).toBe("tool-1"); globalExpect(result[0].result).toBe("Tool result"); globalExpect(result[0].actionExecutionId).toBe("tool-call-1"); }); test("should handle a mix of message types", () => { const aguiMessages = [ { id: "dev-1", role: "developer", content: "Can you run a function?" }, { id: "assistant-1", role: "assistant", content: "Yes, I'll run it", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "testFunction", arguments: JSON.stringify({ param: "value" }) } } ] }, { id: "tool-1", role: "tool", content: "Function result", toolCallId: "tool-call-1" } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(4); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].id).toBe("dev-1"); globalExpect(result[1]).toBeInstanceOf(TextMessage); globalExpect(result[1].id).toBe("assistant-1"); globalExpect(result[2]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[2].id).toBe("tool-call-1"); globalExpect(result[3]).toBeInstanceOf(ResultMessage); globalExpect(result[3].id).toBe("tool-1"); }); test("should handle a mix of message types including user messages", () => { const aguiMessages = [ { id: "user-1", role: "user", content: "Can you help me?" }, { id: "assistant-1", role: "assistant", content: "Yes, I'll help you", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "helpFunction", arguments: JSON.stringify({ query: "help" }) } } ] }, { id: "tool-1", role: "tool", content: "Help result", toolCallId: "tool-call-1" }, { id: "user-2", role: "user", content: "Thank you!" } ]; const result = aguiToGQL(aguiMessages); globalExpect(result).toHaveLength(5); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].id).toBe("user-1"); globalExpect(result[0].role).toBe(Role.User); globalExpect(result[1]).toBeInstanceOf(TextMessage); globalExpect(result[1].id).toBe("assistant-1"); globalExpect(result[1].role).toBe(Role.Assistant); globalExpect(result[2]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[2].id).toBe("tool-call-1"); globalExpect(result[3]).toBeInstanceOf(ResultMessage); globalExpect(result[3].id).toBe("tool-1"); globalExpect(result[4]).toBeInstanceOf(TextMessage); globalExpect(result[4].id).toBe("user-2"); globalExpect(result[4].role).toBe(Role.User); }); }); describe("aguiMessageWithRenderToGQL", () => { test("should handle assistant message with tool calls and render function", () => { const mockRender = () => "Test Render"; const aguiMessage = { id: "assistant-1", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "testFunction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { testFunction: { name: "testFunction" } }; const result = aguiMessageWithRenderToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.testFunction.render).toBe(mockRender); }); test("should handle assistant message with render function but no tool calls", () => { const mockRender = () => "Agent State Render"; const aguiMessage = { id: "agent-state-1", role: "assistant", generativeUI: mockRender }; const coAgentStateRenders = {}; const result = aguiMessageWithRenderToGQL(aguiMessage, void 0, coAgentStateRenders); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(AgentStateMessage); globalExpect(result[0].agentName).toBe("unknown"); globalExpect(coAgentStateRenders.unknown.render).toBe(mockRender); }); test("should handle regular assistant message without render function", () => { const aguiMessage = { id: "assistant-1", role: "assistant", content: "Regular assistant message" }; const result = aguiMessageWithRenderToGQL(aguiMessage); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].content).toBe("Regular assistant message"); }); test("should handle non-assistant messages normally", () => { const aguiMessage = { id: "user-1", role: "user", content: "User message" }; const result = aguiMessageWithRenderToGQL(aguiMessage); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[0].role).toBe(Role.User); }); test("should handle multiple tool calls with render functions", () => { const mockRender1 = () => "Render 1"; const mockRender2 = () => "Render 2"; const aguiMessage = { id: "assistant-1", role: "assistant", content: "I'll execute multiple functions", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "firstFunction", arguments: JSON.stringify({ param: "value1" }) } }, { id: "tool-call-2", type: "function", function: { name: "secondFunction", arguments: JSON.stringify({ param: "value2" }) } } ], generativeUI: mockRender1 }; const actions = { firstFunction: { name: "firstFunction" }, secondFunction: { name: "secondFunction" } }; const result = aguiMessageWithRenderToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(3); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[2]).toBeInstanceOf(ActionExecutionMessage); Object.values(actions).forEach((action) => { globalExpect(action.render).toBe(mockRender1); }); }); test("should verify render function receives correct props including name", () => { const mockRender = vi.fn( (props) => `Rendered: ${props.name} with args: ${JSON.stringify(props.args)}` ); const aguiMessage = { id: "assistant-render-props", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-render-props", type: "function", function: { name: "testFunction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { testFunction: { name: "testFunction" } }; const result = aguiMessageWithRenderToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.testFunction.render).toBe(mockRender); if (actions.testFunction.render) { actions.testFunction.render({ status: "inProgress", args: { param: "value" }, result: void 0, respond: () => { }, messageId: "tool-call-render-props", name: "testFunction" }); globalExpect(mockRender).toHaveBeenCalledWith({ status: "inProgress", args: { param: "value" }, result: void 0, respond: globalExpect.any(Function), messageId: "tool-call-render-props", name: "testFunction" }); } }); }); describe("aguiImageMessageToGQLMessage", () => { test("should throw error for missing format or bytes in image message", () => { const aguiMessage = { id: "image-1", role: "assistant", content: "Image message" }; globalExpect(() => aguiMessageWithImageToGQLMessage(aguiMessage)).toThrow( "Cannot convert message to ImageMessage: missing format or bytes" ); }); test("should convert valid assistant image message", () => { const aguiMessage = { id: "image-2", role: "assistant", image: { format: "jpeg", bytes: "base64stringdata" } }; const result = aguiMessageWithImageToGQLMessage(aguiMessage); globalExpect(result).toBeInstanceOf(ImageMessage); globalExpect(result.id).toBe("image-2"); globalExpect(result.format).toBe("jpeg"); globalExpect(result.bytes).toBe("base64stringdata"); globalExpect(result.role).toBe(Role.Assistant); }); test("should convert valid user image message", () => { const aguiMessage = { id: "image-3", role: "user", content: "", image: { format: "png", bytes: "anotherbase64string" } }; const result = aguiMessageWithImageToGQLMessage(aguiMessage); globalExpect(result).toBeInstanceOf(ImageMessage); globalExpect(result.id).toBe("image-3"); globalExpect(result.format).toBe("png"); globalExpect(result.bytes).toBe("anotherbase64string"); globalExpect(result.role).toBe(Role.User); }); }); describe("Wild Card Actions", () => { test("should preserve render function for specific action", () => { const mockRender = () => "Specific Action Render"; const aguiMessage = { id: "assistant-1", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-1", type: "function", function: { name: "specificAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { specificAction: { name: "specificAction" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.specificAction.render).toBe(mockRender); }); test("should preserve render function for wild card action", () => { const mockRender = () => "Wild Card Action Render"; const aguiMessage = { id: "assistant-2", role: "assistant", content: "I'll execute an unknown function", toolCalls: [ { id: "tool-call-2", type: "function", function: { name: "unknownAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions["*"].render).toBe(mockRender); }); test("should prioritize specific action over wild card action", () => { const mockRender = () => "Prioritized Render"; const aguiMessage = { id: "assistant-3", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-3", type: "function", function: { name: "specificAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { specificAction: { name: "specificAction" }, "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.specificAction.render).toBe(mockRender); globalExpect(actions["*"].render).toBeUndefined(); }); test("should not preserve render function when no matching action", () => { const mockRender = () => "Unmatched Render"; const aguiMessage = { id: "assistant-4", role: "assistant", content: "I'll execute an unmatched function", toolCalls: [ { id: "tool-call-4", type: "function", function: { name: "unmatchedAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { otherAction: { name: "otherAction" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.otherAction.render).toBeUndefined(); }); test("should handle multiple tool calls with wild card action", () => { const mockRender = () => "Wild Card Render"; const aguiMessage = { id: "assistant-5", role: "assistant", content: "I'll execute multiple functions", toolCalls: [ { id: "tool-call-5", type: "function", function: { name: "firstFunction", arguments: JSON.stringify({ param: "value1" }) } }, { id: "tool-call-6", type: "function", function: { name: "secondFunction", arguments: JSON.stringify({ param: "value2" }) } } ], generativeUI: mockRender }; const actions = { "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(3); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[2]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle mixed specific and wild card actions", () => { const mockRender = () => "Mixed Render"; const aguiMessage = { id: "assistant-6", role: "assistant", content: "I'll execute mixed functions", toolCalls: [ { id: "tool-call-7", type: "function", function: { name: "specificAction", arguments: JSON.stringify({ param: "value1" }) } }, { id: "tool-call-8", type: "function", function: { name: "unknownAction", arguments: JSON.stringify({ param: "value2" }) } } ], generativeUI: mockRender }; const actions = { specificAction: { name: "specificAction" }, "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(3); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[2]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.specificAction.render).toBe(mockRender); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle no actions provided", () => { const mockRender = () => "No Actions Render"; const aguiMessage = { id: "assistant-7", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-9", type: "function", function: { name: "anyAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const result = aguiToGQL(aguiMessage); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); }); test("should handle empty actions object", () => { const mockRender = () => "Empty Actions Render"; const aguiMessage = { id: "assistant-8", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-10", type: "function", function: { name: "anyAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = {}; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); }); test("should handle actions with null render functions", () => { const mockRender = () => "Null Render Test"; const aguiMessage = { id: "assistant-9", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-11", type: "function", function: { name: "specificAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { specificAction: { name: "specificAction", render: null }, "*": { name: "*", render: null } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.specificAction.render).toBe(mockRender); }); test("should handle actions with undefined render functions", () => { const mockRender = () => "Undefined Render Test"; const aguiMessage = { id: "assistant-10", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-12", type: "function", function: { name: "wildcardAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { "*": { name: "*", render: void 0 } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle tool calls with malformed arguments", () => { const mockRender = () => "Malformed Args Test"; const aguiMessage = { id: "assistant-11", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-13", type: "function", function: { name: "wildcardAction", arguments: "invalid json {" // Malformed JSON } } ], generativeUI: mockRender }; const actions = { "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle tool calls with empty arguments string", () => { const mockRender = () => "Empty Args Test"; const aguiMessage = { id: "assistant-12", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-14", type: "function", function: { name: "wildcardAction", arguments: "" } } ], generativeUI: mockRender }; const actions = { "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle multiple wild card actions in same object", () => { const mockRender = () => "Multiple Wildcards Test"; const aguiMessage = { id: "assistant-13", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-15", type: "function", function: { name: "unknownAction", arguments: JSON.stringify({ param: "value" }) } } ], generativeUI: mockRender }; const actions = { wildcard1: { name: "*" }, wildcard2: { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(actions.wildcard1.render).toBe(mockRender); globalExpect(actions.wildcard2.render).toBeUndefined(); }); test("should handle tool calls with object arguments (backward compatibility)", () => { const mockRender = () => "Object Args Test"; const aguiMessage = { id: "assistant-14", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-16", type: "function", function: { name: "objectArgsAction", arguments: { param: "value" } // Object instead of string } } ], generativeUI: mockRender }; const actions = { "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[1].arguments).toEqual({ param: "value" }); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle tool calls with null/undefined arguments", () => { const mockRender = () => "Null Args Test"; const aguiMessage = { id: "assistant-15", role: "assistant", content: "I'll execute a function", toolCalls: [ { id: "tool-call-17", type: "function", function: { name: "nullArgsAction", arguments: null } } ], generativeUI: mockRender }; const actions = { "*": { name: "*" } }; const result = aguiToGQL(aguiMessage, actions); globalExpect(result).toHaveLength(2); globalExpect(result[0]).toBeInstanceOf(TextMessage); globalExpect(result[1]).toBeInstanceOf(ActionExecutionMessage); globalExpect(result[1].arguments).toEqual({}); globalExpect(actions["*"].render).toBe(mockRender); }); test("should handle tool result messages with object content", () => { const aguiMessage = { id: "tool-result-1", role: "tool", content: { status: "success", data: { value: 42 } }, toolCallId: "tool-call-1", toolName: "testAction" }; const toolCallNames = { "tool-call-1": "testAction" }; const result = aguiToGQL(aguiMessage); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(ResultMessage); globalExpect(result[0].result).toBe('{"status":"success","data":{"value":42}}'); globalExpect(result[0].actionExecutionId).toBe("tool-call-1"); globalExpect(result[0].actionName).toBe("testAction"); }); test("should handle tool result messages with non-string content types", () => { const aguiMessage = { id: "tool-result-2", role: "tool", content: 42, toolCallId: "tool-call-2", toolName: "numberAction" }; const result = aguiToGQL(aguiMessage); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(ResultMessage); globalExpect(result[0].result).toBe("42"); globalExpect(result[0].actionExecutionId).toBe("tool-call-2"); globalExpect(result[0].actionName).toBe("numberAction"); }); test("should handle tool result messages with circular reference content", () => { const circularObj = { status: "success" }; circularObj.self = circularObj; const aguiMessage = { id: "tool-result-3", role: "tool", content: circularObj, toolCallId: "tool-call-3", toolName: "circularAction" }; const result = aguiToGQL(aguiMessage); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(ResultMessage); globalExpect(result[0].result).toBe("[object Object]"); globalExpect(result[0].actionExecutionId).toBe("tool-call-3"); globalExpect(result[0].actionName).toBe("circularAction"); }); test("should handle tool result messages with boolean content", () => { const aguiMessage = { id: "tool-result-4", role: "tool", content: true, toolCallId: "tool-call-4", toolName: "booleanAction" }; const result = aguiToGQL(aguiMessage); globalExpect(result).toHaveLength(1); globalExpect(result[0]).toBeInstanceOf(ResultMessage); globalExpect(result[0].result).toBe("true"); globalExpect(result[0].actionExecutionId).toBe("tool-call-4"); globalExpect(result[0].actionName).toBe("booleanAction"); }); }); }); //# sourceMappingURL=agui-to-gql.test.mjs.map