@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 lines • 74.8 kB
Source Map (JSON)
{"version":3,"sources":["../../src/message-conversion/gql-to-agui.test.ts"],"sourcesContent":["import { describe, test, expect, vi } from \"vitest\";\nimport * as gql from \"../client\";\nimport { MessageStatusCode } from \"../graphql/@generated/graphql\";\nimport {\n  gqlToAGUI,\n  gqlTextMessageToAGUIMessage,\n  gqlResultMessageToAGUIMessage,\n  gqlImageMessageToAGUIMessage,\n  gqlActionExecutionMessageToAGUIMessage,\n} from \"./gql-to-agui\";\nimport { AIMessage } from \"@copilotkit/shared\";\n\ndescribe(\"message-conversion\", () => {\n  describe(\"gqlTextMessageToAGUIMessage\", () => {\n    test(\"should convert developer message\", () => {\n      const gqlMessage = new gql.TextMessage({\n        id: \"dev-message-id\",\n        content: \"Hello from developer\",\n        role: gql.Role.Developer,\n      });\n\n      const result = gqlTextMessageToAGUIMessage(gqlMessage);\n\n      expect(result).toEqual({\n        id: \"dev-message-id\",\n        role: \"developer\",\n        content: \"Hello from developer\",\n      });\n    });\n\n    test(\"should convert system message\", () => {\n      const gqlMessage = new gql.TextMessage({\n        id: \"system-message-id\",\n        content: \"System instruction\",\n        role: gql.Role.System,\n      });\n\n      const result = gqlTextMessageToAGUIMessage(gqlMessage);\n\n      expect(result).toEqual({\n        id: \"system-message-id\",\n        role: \"system\",\n        content: \"System instruction\",\n      });\n    });\n\n    test(\"should convert assistant message\", () => {\n      const gqlMessage = new gql.TextMessage({\n        id: \"assistant-message-id\",\n        content: \"Assistant response\",\n        role: gql.Role.Assistant,\n      });\n\n      const result = gqlTextMessageToAGUIMessage(gqlMessage);\n\n      expect(result).toEqual({\n        id: \"assistant-message-id\",\n        role: \"assistant\",\n        content: \"Assistant response\",\n      });\n    });\n\n    test(\"should throw error for unknown role\", () => {\n      const gqlMessage = new gql.TextMessage({\n        id: \"unknown-message-id\",\n        content: \"Unknown message\",\n        role: \"unknown\" as any,\n      });\n\n      expect(() => gqlTextMessageToAGUIMessage(gqlMessage)).toThrow(\"Unknown message role\");\n    });\n  });\n\n  describe(\"gqlResultMessageToAGUIMessage\", () => {\n    test(\"should convert result message to tool message\", () => {\n      const gqlMessage = new gql.ResultMessage({\n        id: \"result-id\",\n        result: \"Function result data\",\n        actionExecutionId: \"action-exec-123\",\n        actionName: \"testAction\",\n      });\n\n      const result = gqlResultMessageToAGUIMessage(gqlMessage);\n\n      expect(result).toEqual({\n        id: \"result-id\",\n        role: \"tool\",\n        content: \"Function result data\",\n        toolCallId: \"action-exec-123\",\n        toolName: \"testAction\",\n      });\n    });\n  });\n\n  describe(\"gqlToAGUI\", () => {\n    test(\"should convert an array of text messages\", () => {\n      const gqlMessages = [\n        new gql.TextMessage({\n          id: \"dev-1\",\n          content: \"Hello\",\n          role: gql.Role.Developer,\n        }),\n        new gql.TextMessage({\n          id: \"assistant-1\",\n          content: \"Hi there\",\n          role: gql.Role.Assistant,\n        }),\n      ];\n\n      const result = gqlToAGUI(gqlMessages);\n\n      expect(result).toHaveLength(2);\n      expect(result[0]).toEqual({\n        id: \"dev-1\",\n        role: \"developer\",\n        content: \"Hello\",\n      });\n      expect(result[1]).toEqual({\n        id: \"assistant-1\",\n        role: \"assistant\",\n        content: \"Hi there\",\n      });\n    });\n\n    test(\"should handle agent state messages\", () => {\n      const gqlMessages = [new gql.AgentStateMessage({ id: \"agent-state-1\" })];\n\n      const result = gqlToAGUI(gqlMessages);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"agent-state-1\",\n        role: \"assistant\",\n      });\n    });\n\n    // test(\"should throw error for unknown message type\", () => {\n    //   // Create a message with unknown type\n    //   const unknownMessage = new gql.Message({ id: \"unknown-1\" });\n    //   // Override the type checking methods to simulate unknown type\n    //   unknownMessage.isTextMessage = () => false as any;\n    //   unknownMessage.isResultMessage = () => false as any;\n    //   unknownMessage.isActionExecutionMessage = () => false as any;\n    //   unknownMessage.isAgentStateMessage = () => false as any;\n    //   unknownMessage.isImageMessage = () => false as any;\n\n    //   expect(() => gqlToAGUI([unknownMessage])).toThrow(\"Unknown message type\");\n    // });\n\n    test(\"should handle a mix of message types\", () => {\n      const gqlMessages = [\n        new gql.TextMessage({\n          id: \"dev-1\",\n          content: \"Run action\",\n          role: gql.Role.Developer,\n        }),\n        new gql.TextMessage({\n          id: \"assistant-1\",\n          content: \"I'll run the action\",\n          role: gql.Role.Assistant,\n        }),\n        new gql.ResultMessage({\n          id: \"result-1\",\n          result: \"Action result\",\n          actionExecutionId: \"action-exec-1\",\n          actionName: \"testAction\",\n        }),\n      ];\n\n      const result = gqlToAGUI(gqlMessages);\n\n      expect(result).toHaveLength(3);\n      expect(result[0]).toEqual({\n        id: \"dev-1\",\n        role: \"developer\",\n        content: \"Run action\",\n      });\n      expect(result[1]).toEqual({\n        id: \"assistant-1\",\n        role: \"assistant\",\n        content: \"I'll run the action\",\n      });\n      expect(result[2]).toEqual({\n        id: \"result-1\",\n        role: \"tool\",\n        content: \"Action result\",\n        toolCallId: \"action-exec-1\",\n        toolName: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution messages with parent messages\", () => {\n      const assistantMsg = new gql.TextMessage({\n        id: \"assistant-1\",\n        content: \"I'll execute an action\",\n        role: gql.Role.Assistant,\n      });\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        parentMessageId: \"assistant-1\",\n      });\n\n      const result = gqlToAGUI([assistantMsg, actionExecMsg]);\n\n      // Now we expect 2 messages: the original assistant message and the action execution message\n      expect(result).toHaveLength(2);\n      expect(result[0]).toEqual({\n        id: \"assistant-1\",\n        role: \"assistant\",\n        content: \"I'll execute an action\",\n      });\n      expect(result[1]).toEqual({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"testAction\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"testAction\",\n              arguments: JSON.stringify({ param: \"value\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n    });\n\n    test(\"should handle multiple action execution messages for the same parent\", () => {\n      const assistantMsg = new gql.TextMessage({\n        id: \"assistant-1\",\n        content: \"I'll execute multiple actions\",\n        role: gql.Role.Assistant,\n      });\n\n      const action1 = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"firstAction\",\n        arguments: { param: \"value1\" },\n        parentMessageId: \"assistant-1\",\n      });\n\n      const action2 = new gql.ActionExecutionMessage({\n        id: \"action-2\",\n        name: \"secondAction\",\n        arguments: { param: \"value2\" },\n        parentMessageId: \"assistant-1\",\n      });\n\n      const result = gqlToAGUI([assistantMsg, action1, action2]);\n\n      // Now we expect 3 messages: the original assistant message and 2 separate action execution messages\n      expect(result).toHaveLength(3);\n      expect(result[0]).toEqual({\n        id: \"assistant-1\",\n        role: \"assistant\",\n        content: \"I'll execute multiple actions\",\n      });\n      expect(result[1]).toEqual({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"firstAction\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"firstAction\",\n              arguments: JSON.stringify({ param: \"value1\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n      expect(result[2]).toEqual({\n        id: \"action-2\",\n        role: \"assistant\",\n        name: \"secondAction\",\n        toolCalls: [\n          {\n            id: \"action-2\",\n            function: {\n              name: \"secondAction\",\n              arguments: JSON.stringify({ param: \"value2\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n    });\n\n    test(\"should not add toolCalls to non-assistant messages\", () => {\n      const developerMsg = new gql.TextMessage({\n        id: \"dev-1\",\n        content: \"Developer message\",\n        role: gql.Role.Developer,\n      });\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        parentMessageId: \"dev-1\", // This should be ignored since parent is not assistant\n      });\n\n      const result = gqlToAGUI([developerMsg, actionExecMsg]);\n\n      // Now we expect 2 messages: the developer message and the action execution as assistant message\n      expect(result).toHaveLength(2);\n      expect(result[0]).toEqual({\n        id: \"dev-1\",\n        role: \"developer\",\n        content: \"Developer message\",\n      });\n      // The action execution becomes its own assistant message regardless of parent\n      expect(result[1]).toEqual({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"testAction\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"testAction\",\n              arguments: JSON.stringify({ param: \"value\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n    });\n\n    test(\"should handle action execution messages without actions context\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n      });\n\n      const result = gqlToAGUI([actionExecMsg]);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"testAction\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"testAction\",\n              arguments: JSON.stringify({ param: \"value\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n      // Should not have render functions without actions context\n      expect(result[0]).not.toHaveProperty(\"render\");\n      expect(result[0]).not.toHaveProperty(\"renderAndWaitForResponse\");\n    });\n\n    test(\"should handle action execution messages with actions context and render functions\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        status: { code: MessageStatusCode.Pending },\n      });\n\n      const mockRender = vi.fn();\n      const mockRenderAndWaitForResponse = (props: any) => \"Test Render With Response\";\n\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: mockRender,\n          renderAndWaitForResponse: mockRenderAndWaitForResponse,\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg], actions);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toMatchObject({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"testAction\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"testAction\",\n              arguments: JSON.stringify({ param: \"value\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n\n      // Should have generativeUI function\n      expect(result[0]).toHaveProperty(\"generativeUI\");\n      expect(typeof (result[0] as any).generativeUI).toBe(\"function\");\n    });\n\n    test(\"should provide correct status in generativeUI function props\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        status: { code: MessageStatusCode.Pending },\n      });\n\n      const mockRender = vi.fn();\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: mockRender,\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg], actions);\n\n      // Call the generativeUI function\n      (result[0] as any).generativeUI?.();\n\n      expect(mockRender).toHaveBeenCalledWith({\n        status: \"inProgress\",\n        args: { param: \"value\" },\n        result: undefined,\n        respond: expect.any(Function),\n        messageId: \"action-1\",\n        // Regular actions should NOT have the name property\n      });\n    });\n\n    test(\"should provide executing status when not pending\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        status: { code: MessageStatusCode.Success },\n      });\n\n      const mockRender = vi.fn();\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: mockRender,\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg], actions);\n\n      // Call the generativeUI function\n      (result[0] as any).generativeUI?.();\n\n      expect(mockRender).toHaveBeenCalledWith({\n        status: \"executing\",\n        args: { param: \"value\" },\n        result: undefined,\n        respond: expect.any(Function),\n        messageId: \"action-1\",\n        // Regular actions should NOT have the name property\n      });\n    });\n\n    test(\"should provide complete status when result is available\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        status: { code: MessageStatusCode.Success },\n      });\n\n      const resultMsg = new gql.ResultMessage({\n        id: \"result-1\",\n        result: \"Action completed successfully\",\n        actionExecutionId: \"action-1\",\n        actionName: \"testAction\",\n      });\n\n      const mockRender = vi.fn();\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: mockRender,\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg, resultMsg], actions);\n\n      // Find the action execution message result (not the tool result)\n      const actionMessage = result.find((msg) => msg.role === \"assistant\" && \"toolCalls\" in msg);\n\n      // Call the generativeUI function\n      (actionMessage as any)?.generativeUI?.();\n\n      expect(mockRender).toHaveBeenCalledWith({\n        status: \"complete\",\n        args: { param: \"value\" },\n        result: \"Action completed successfully\",\n        respond: expect.any(Function),\n        messageId: \"action-1\",\n        // Regular actions should NOT have the name property\n      });\n    });\n\n    test(\"should handle generativeUI function props override\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        status: { code: MessageStatusCode.Pending },\n      });\n\n      const mockRender = vi.fn();\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: mockRender,\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg], actions);\n\n      // Call with custom props\n      (result[0] as any).generativeUI?.({\n        status: \"custom\",\n        customProp: \"test\",\n        respond: () => \"custom respond\",\n      });\n\n      expect(mockRender).toHaveBeenCalledWith({\n        status: \"custom\",\n        args: { param: \"value\" },\n        result: undefined,\n        respond: expect.any(Function),\n        customProp: \"test\",\n        messageId: \"action-1\",\n        // Regular actions should NOT have the name property\n      });\n    });\n\n    test(\"should handle missing render functions gracefully\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n      });\n\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          // No render functions provided\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg], actions);\n\n      expect(result[0]).toMatchObject({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"testAction\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"testAction\",\n              arguments: JSON.stringify({ param: \"value\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n\n      // Should have undefined generativeUI functions\n      expect((result[0] as any).generativeUI).toBeUndefined();\n    });\n\n    test(\"should handle action not found in actions context\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"unknownAction\",\n        arguments: { param: \"value\" },\n      });\n\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: () => \"Test\",\n        },\n      };\n\n      const result = gqlToAGUI([actionExecMsg], actions);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"action-1\",\n        role: \"assistant\",\n        name: \"unknownAction\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"unknownAction\",\n              arguments: JSON.stringify({ param: \"value\" }),\n            },\n            type: \"function\",\n          },\n        ],\n      });\n\n      // Should not have generativeUI functions when action not found\n      expect(result[0]).not.toHaveProperty(\"generativeUI\");\n    });\n\n    test(\"should handle agent state messages with coAgentStateRenders\", () => {\n      const agentStateMsg = new gql.AgentStateMessage({\n        id: \"agent-state-1\",\n        agentName: \"testAgent\",\n        state: { status: \"running\", data: \"test data\" },\n        role: gql.Role.Assistant,\n      });\n\n      const mockRender = vi.fn();\n      const coAgentStateRenders = {\n        testAgent: {\n          name: \"testAgent\",\n          render: mockRender,\n        },\n      };\n\n      const result = gqlToAGUI([agentStateMsg], undefined, coAgentStateRenders);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"agent-state-1\",\n        role: \"assistant\",\n        agentName: \"testAgent\",\n        state: { status: \"running\", data: \"test data\" },\n        generativeUI: expect.any(Function),\n      });\n\n      // Should have generativeUI function\n      expect(result[0]).toHaveProperty(\"generativeUI\");\n      expect(typeof (result[0] as any).generativeUI).toBe(\"function\");\n\n      // Call the generativeUI function\n      (result[0] as any).generativeUI?.();\n\n      expect(mockRender).toHaveBeenCalledWith({\n        state: { status: \"running\", data: \"test data\" },\n      });\n    });\n\n    test(\"should handle agent state messages without coAgentStateRenders\", () => {\n      const agentStateMsg = new gql.AgentStateMessage({\n        id: \"agent-state-1\",\n        agentName: \"testAgent\",\n        state: { status: \"running\", data: \"test data\" },\n        role: gql.Role.Assistant,\n      });\n\n      const result = gqlToAGUI([agentStateMsg]);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"agent-state-1\",\n        role: \"assistant\",\n        agentName: \"testAgent\",\n        state: { status: \"running\", data: \"test data\" },\n      });\n\n      // Should not have generativeUI functions without coAgentStateRenders\n      expect(result[0]).not.toHaveProperty(\"generativeUI\");\n    });\n\n    test(\"should handle agent state messages with agent not found in coAgentStateRenders\", () => {\n      const agentStateMsg = new gql.AgentStateMessage({\n        id: \"agent-state-1\",\n        agentName: \"unknownAgent\",\n        state: { status: \"running\", data: \"test data\" },\n        role: gql.Role.Assistant,\n      });\n\n      const coAgentStateRenders = {\n        testAgent: {\n          name: \"testAgent\",\n          render: () => \"Test\",\n        },\n      };\n\n      const result = gqlToAGUI([agentStateMsg], undefined, coAgentStateRenders);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"agent-state-1\",\n        role: \"assistant\",\n        agentName: \"unknownAgent\",\n        state: { status: \"running\", data: \"test data\" },\n      });\n\n      // Should not have generativeUI functions when agent not found\n      expect(result[0]).not.toHaveProperty(\"generativeUI\");\n    });\n\n    test(\"should handle user role messages\", () => {\n      const userMsg = new gql.TextMessage({\n        id: \"user-1\",\n        content: \"Hello from user\",\n        role: gql.Role.User,\n      });\n\n      const result = gqlToAGUI([userMsg]);\n\n      expect(result).toHaveLength(1);\n      expect(result[0]).toEqual({\n        id: \"user-1\",\n        role: \"user\",\n        content: \"Hello from user\",\n      });\n    });\n\n    test(\"should handle mixed message types including agent state messages\", () => {\n      const textMsg = new gql.TextMessage({\n        id: \"text-1\",\n        content: \"Hello\",\n        role: gql.Role.Assistant,\n      });\n\n      const agentStateMsg = new gql.AgentStateMessage({\n        id: \"agent-state-1\",\n        agentName: \"testAgent\",\n        state: { status: \"running\" },\n        role: gql.Role.Assistant,\n      });\n\n      const mockRender = vi.fn();\n      const coAgentStateRenders = {\n        testAgent: {\n          name: \"testAgent\",\n          render: mockRender,\n        },\n      };\n\n      const result = gqlToAGUI([textMsg, agentStateMsg], undefined, coAgentStateRenders);\n\n      expect(result).toHaveLength(2);\n      expect(result[0]).toEqual({\n        id: \"text-1\",\n        role: \"assistant\",\n        content: \"Hello\",\n      });\n      expect(result[1]).toMatchObject({\n        id: \"agent-state-1\",\n        role: \"assistant\",\n        agentName: \"testAgent\",\n        state: { status: \"running\" },\n        generativeUI: expect.any(Function),\n      });\n      expect(result[1]).toHaveProperty(\"generativeUI\");\n    });\n  });\n\n  describe(\"gqlImageMessageToAGUIMessage\", () => {\n    test(\"should throw error for invalid image format\", () => {\n      const invalidImageMsg = new gql.ImageMessage({\n        id: \"img-1\",\n        format: \"bmp\", // not in VALID_IMAGE_FORMATS\n        bytes: \"somebase64string\",\n        role: gql.Role.User,\n      });\n      expect(() => gqlImageMessageToAGUIMessage(invalidImageMsg)).toThrow(\"Invalid image format\");\n    });\n\n    test(\"should throw error for empty image bytes\", () => {\n      const invalidImageMsg = new gql.ImageMessage({\n        id: \"img-2\",\n        format: \"jpeg\",\n        bytes: \"\",\n        role: gql.Role.User,\n      });\n      expect(() => gqlImageMessageToAGUIMessage(invalidImageMsg)).toThrow(\n        \"Image bytes must be a non-empty string\",\n      );\n    });\n\n    test(\"should convert valid image message\", () => {\n      const validImageMsg = new gql.ImageMessage({\n        id: \"img-3\",\n        format: \"jpeg\",\n        bytes: \"somebase64string\",\n        role: gql.Role.User,\n      });\n      const result = gqlImageMessageToAGUIMessage(validImageMsg);\n      expect(result).toMatchObject({\n        id: \"img-3\",\n        role: \"user\",\n        content: \"\",\n        image: {\n          format: \"jpeg\",\n          bytes: \"somebase64string\",\n        },\n      });\n    });\n\n    test(\"should convert valid user image message\", () => {\n      const validImageMsg = new gql.ImageMessage({\n        id: \"img-user-1\",\n        format: \"jpeg\",\n        bytes: \"userbase64string\",\n        role: gql.Role.User,\n      });\n      const result = gqlImageMessageToAGUIMessage(validImageMsg);\n      expect(result).toMatchObject({\n        id: \"img-user-1\",\n        role: \"user\",\n        content: \"\",\n        image: {\n          format: \"jpeg\",\n          bytes: \"userbase64string\",\n        },\n      });\n    });\n\n    test(\"should convert valid assistant image message\", () => {\n      const validImageMsg = new gql.ImageMessage({\n        id: \"img-assistant-1\",\n        format: \"png\",\n        bytes: \"assistantbase64string\",\n        role: gql.Role.Assistant,\n      });\n      const result = gqlImageMessageToAGUIMessage(validImageMsg);\n      expect(result).toMatchObject({\n        id: \"img-assistant-1\",\n        role: \"assistant\",\n        content: \"\",\n        image: {\n          format: \"png\",\n          bytes: \"assistantbase64string\",\n        },\n      });\n    });\n  });\n\n  describe(\"Wild Card Actions\", () => {\n    test(\"should handle action execution with specific action\", () => {\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: vi.fn((props) => `Rendered: ${props.args.test}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-1\",\n        name: \"testAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-1\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-1\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-1\",\n            function: {\n              name: \"testAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with wild card action\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Wildcard rendered: ${props.args.test}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-2\",\n        name: \"unknownAction\",\n        arguments: { test: \"wildcard-value\" },\n        parentMessageId: \"parent-2\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-2\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-2\",\n            function: {\n              name: \"unknownAction\",\n              arguments: '{\"test\":\"wildcard-value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"unknownAction\",\n      });\n    });\n\n    test(\"should pass tool name to wildcard action render function\", () => {\n      const mockRender = vi.fn(\n        (props) => `Wildcard rendered: ${props.name} with args: ${JSON.stringify(props.args)}`,\n      );\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: mockRender,\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-wildcard-name\",\n        name: \"testTool\",\n        arguments: { param: \"value\" },\n        parentMessageId: \"parent-wildcard-name\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      // Call the generativeUI function to trigger the render\n      (result as any).generativeUI?.();\n\n      // Verify that the render function was called with the name property\n      expect(mockRender).toHaveBeenCalledWith(\n        expect.objectContaining({\n          name: \"testTool\",\n          args: { param: \"value\" },\n        }),\n      );\n    });\n\n    test(\"should pass tool name to regular action render function\", () => {\n      const mockRender = vi.fn((props) => `Regular action rendered: ${JSON.stringify(props.args)}`);\n      const actions = {\n        testAction: {\n          name: \"testAction\",\n          render: mockRender,\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-regular-name\",\n        name: \"testAction\",\n        arguments: { param: \"value\" },\n        parentMessageId: \"parent-regular-name\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      // Call the generativeUI function to trigger the render\n      (result as any).generativeUI?.();\n\n      // Verify that the render function was called with the correct props\n      // Regular actions should NOT have the name property\n      expect(mockRender).toHaveBeenCalledWith(\n        expect.objectContaining({\n          args: { param: \"value\" },\n          // name property should NOT be present for regular actions\n        }),\n      );\n\n      // Verify that the name property is NOT present\n      const callArgs = mockRender.mock.calls[0][0];\n      expect(callArgs).not.toHaveProperty(\"name\");\n    });\n\n    test(\"should prioritize specific action over wild card action\", () => {\n      const actions = {\n        specificAction: {\n          name: \"specificAction\",\n          render: vi.fn((props) => \"Specific action rendered\"),\n        },\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => \"Wildcard action rendered\"),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-3\",\n        name: \"specificAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-3\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-3\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-3\",\n            function: {\n              name: \"specificAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"specificAction\",\n      });\n    });\n\n    test(\"should handle action execution without any matching actions\", () => {\n      const actions = {\n        otherAction: {\n          name: \"otherAction\",\n          render: vi.fn(),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-4\",\n        name: \"unmatchedAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-4\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-4\",\n        role: \"assistant\",\n        toolCalls: [\n          {\n            id: \"action-4\",\n            function: {\n              name: \"unmatchedAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        name: \"unmatchedAction\",\n      });\n      expect(result).not.toHaveProperty(\"generativeUI\");\n    });\n\n    test(\"should handle action execution with no actions provided\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-5\",\n        name: \"anyAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-5\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg);\n\n      expect(result).toMatchObject({\n        id: \"action-5\",\n        role: \"assistant\",\n        toolCalls: [\n          {\n            id: \"action-5\",\n            function: {\n              name: \"anyAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        name: \"anyAction\",\n      });\n      expect(result).not.toHaveProperty(\"generativeUI\");\n    });\n\n    test(\"should handle action execution with completed result\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Result: ${props.result}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-6\",\n        name: \"testAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-6\",\n      });\n\n      const actionResults = new Map([[\"action-6\", \"completed result\"]]);\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions, actionResults);\n\n      expect(result).toMatchObject({\n        id: \"action-6\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-6\",\n            function: {\n              name: \"testAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with executing status\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Status: ${props.status}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-7\",\n        name: \"testAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-7\",\n        status: { code: MessageStatusCode.Success },\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-7\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-7\",\n            function: {\n              name: \"testAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with pending status\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Status: ${props.status}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-8\",\n        name: \"testAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-8\",\n        status: { code: MessageStatusCode.Pending },\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-8\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-8\",\n            function: {\n              name: \"testAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with failed status\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Status: ${props.status}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-9\",\n        name: \"testAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-9\",\n        status: { code: MessageStatusCode.Failed },\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-9\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-9\",\n            function: {\n              name: \"testAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with undefined status\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Status: ${props.status}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-10\",\n        name: \"testAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-10\",\n        // No status field\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-10\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-10\",\n            function: {\n              name: \"testAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with empty arguments\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Args: ${JSON.stringify(props.args)}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-11\",\n        name: \"testAction\",\n        arguments: {},\n        parentMessageId: \"parent-11\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-11\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-11\",\n            function: {\n              name: \"testAction\",\n              arguments: \"{}\",\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with null arguments\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Args: ${JSON.stringify(props.args)}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-12\",\n        name: \"testAction\",\n        arguments: null as any,\n        parentMessageId: \"parent-12\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-12\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-12\",\n            function: {\n              name: \"testAction\",\n              arguments: \"null\",\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle action execution with complex nested arguments\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Complex: ${JSON.stringify(props.args)}`),\n        },\n      };\n\n      const complexArgs = {\n        nested: {\n          array: [1, 2, 3],\n          object: { key: \"value\" },\n          nullValue: null,\n          undefinedValue: undefined,\n        },\n        string: \"test\",\n        number: 42,\n        boolean: true,\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-13\",\n        name: \"testAction\",\n        arguments: complexArgs,\n        parentMessageId: \"parent-13\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-13\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-13\",\n            function: {\n              name: \"testAction\",\n              arguments: JSON.stringify(complexArgs),\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"testAction\",\n      });\n    });\n\n    test(\"should handle multiple wild card actions (should use first one)\", () => {\n      const actions = {\n        wildcard1: {\n          name: \"*\",\n          render: vi.fn((props) => \"First wildcard\"),\n        },\n        wildcard2: {\n          name: \"*\",\n          render: vi.fn((props) => \"Second wildcard\"),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-14\",\n        name: \"unknownAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-14\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions);\n\n      expect(result).toMatchObject({\n        id: \"action-14\",\n        role: \"assistant\",\n        content: \"\",\n        toolCalls: [\n          {\n            id: \"action-14\",\n            function: {\n              name: \"unknownAction\",\n              arguments: '{\"test\":\"value\"}',\n            },\n            type: \"function\",\n          },\n        ],\n        generativeUI: expect.any(Function),\n        name: \"unknownAction\",\n      });\n    });\n\n    test(\"should parse string results in generativeUI props\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Result: ${JSON.stringify(props.result)}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-string-result\",\n        name: \"stringResultAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-string\",\n      });\n\n      const actionResults = new Map<string, string>();\n      actionResults.set(\"action-string-result\", '{\"parsed\": true, \"value\": 42}');\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions, actionResults);\n\n      expect((result as AIMessage).generativeUI).toBeDefined();\n      // Call the render function to test the result parsing\n      const renderResult = (result as AIMessage).generativeUI!({\n        result: '{\"from\": \"props\", \"data\": \"test\"}',\n      });\n\n      // Verify the render function was called and the result was parsed\n      expect(actions[\"*\"].render).toHaveBeenCalledWith(\n        expect.objectContaining({\n          result: { from: \"props\", data: \"test\" }, // Should be parsed from string\n          args: { test: \"value\" },\n          status: \"complete\",\n          messageId: \"action-string-result\",\n        }),\n      );\n    });\n\n    test(\"should handle malformed JSON strings gracefully in results\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Result: ${JSON.stringify(props.result)}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-malformed\",\n        name: \"malformedAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-malformed\",\n      });\n\n      const actionResults = new Map<string, string>();\n      actionResults.set(\"action-malformed\", \"invalid json {\");\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions, actionResults);\n\n      expect((result as AIMessage).generativeUI).toBeDefined();\n      // Call the render function to test malformed JSON handling\n      const renderResult = (result as AIMessage).generativeUI!({\n        result: \"invalid json {\",\n      });\n\n      // Verify the render function was called with the original string (unparsed)\n      expect(actions[\"*\"].render).toHaveBeenCalledWith(\n        expect.objectContaining({\n          result: \"invalid json {\", // Should remain as string due to parse error\n          args: { test: \"value\" },\n          status: \"complete\",\n          messageId: \"action-malformed\",\n        }),\n      );\n    });\n\n    test(\"should handle non-string results without parsing\", () => {\n      const actions = {\n        \"*\": {\n          name: \"*\",\n          render: vi.fn((props) => `Result: ${JSON.stringify(props.result)}`),\n        },\n      };\n\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-object-result\",\n        name: \"objectResultAction\",\n        arguments: { test: \"value\" },\n        parentMessageId: \"parent-object\",\n      });\n\n      const actionResults = new Map<string, string>();\n      actionResults.set(\"action-object-result\", '{\"already\": \"parsed\"}');\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg, actions, actionResults);\n\n      expect((result as AIMessage).generativeUI).toBeDefined();\n      // Call the render function with an object result\n      const renderResult = (result as AIMessage).generativeUI!({\n        result: { from: \"props\", data: \"object\" },\n      });\n\n      // Verify the render function was called with the object as-is\n      expect(actions[\"*\"].render).toHaveBeenCalledWith(\n        expect.objectContaining({\n          result: { from: \"props\", data: \"object\" }, // Should remain as object\n          args: { test: \"value\" },\n          status: \"complete\",\n          messageId: \"action-object-result\",\n        }),\n      );\n    });\n\n    test(\"should handle action execution arguments correctly with simplified conversion\", () => {\n      const actionExecMsg = new gql.ActionExecutionMessage({\n        id: \"action-simplified\",\n        name: \"simplifiedAction\",\n        arguments: { complex: { nested: \"value\" }, array: [1, 2, 3] },\n        parentMessageId: \"parent-simplified\",\n      });\n\n      const result = gqlActionExecutionMessageToAGUIMessage(actionExecMsg);\n\n      expect(result).toMatchObject({\n        id: \"action-simplified\",\n        role: \"assistant\",\n        toolCalls: [\n          {\n            id: \"action-simplified\",\n            function: {\n              name: \"simplifiedAction\",\n              arguments: '{\"complex\":{\"nested\":\"value\"},\"array\":[1,2,3]}',\n            },\n            type: \"function\",\n          },\n        ],\n        name: \"simplifiedAction\",\n      });\n    });\n  });\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,SAAS,sBAAsB,MAAM;AACnC,WAAS,+BAA+B,MAAM;AAC5C,SAAK,oCAAoC,MAAM;AAC7C,YAAM,aAAa,IAAQ,YAAY;AAAA,QACrC,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,MAAU,KAAK;AAAA,MACjB,CAAC;AAED,YAAM,SAAS,4BAA4B,UAAU;AAErD,mBAAO,MAAM,EAAE,QAAQ;AAAA,QACrB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AAED,SAAK,iCAAiC,MAAM;AAC1C,YAAM,aAAa,IAAQ,YAAY;AAAA,QACrC,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,MAAU,KAAK;AAAA,MACjB,CAAC;AAED,YAAM,SAAS,4BAA4B,UAAU;AAErD,mBAAO,MAAM,EAAE,QAAQ;AAAA,QACrB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AAED,SAAK,oCAAoC,MAAM;AAC7C,YAAM,aAAa,IAAQ,YAAY;AAAA,QACrC,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,MAAU,KAAK;AAAA,MACjB,CAAC;AAED,YAAM,SAAS,4BAA4B,UAAU;AAErD,mBAAO,MAAM,EAAE,QAAQ;AAAA,QACrB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACH,CAAC;AAED,SAAK,uCAAuC,MAAM;AAChD,YAAM,aAAa,IAAQ,YAAY;AAAA,QACrC,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,MAAM;AAAA,MACR,CAAC;AAED,mBAAO,MAAM,4BAA4B,UAAU,CAAC,EAAE,QAAQ,sBAAsB;AAAA,IACtF,CAAC;AAAA,EACH,CAAC;AAED,WAAS,iCAAiC,MAAM;AAC9C,SAAK,iDAAiD,MAAM;AAC1D,YAAM,aAAa,IAAQ,cAAc;AAAA,QACvC,IAAI;AAAA,QACJ,QAAQ;AAAA,QACR,mBAAmB;AAAA,QACnB,YAAY;AAAA,MACd,CAAC;AAED,YAAM,SAAS,8BAA8B,UAAU;AAEvD,mBAAO,MAAM,EAAE,QAAQ;AAAA,QACrB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,UAAU;AAAA,MACZ,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AAED,WAAS,aAAa,MAAM;AAC1B,SAAK,4CAA4C,MAAM;AACrD,YAAM,cAAc;AAAA,QAClB,IAAQ,YAAY;AAAA,