import { h, watch } from "vue"; import type { Component, WatchSource, VNodeChild } from "vue"; import type { StandardSchemaV1, InferSchemaOutput } from "@copilotkit/shared"; import { useCopilotKit } from "../providers/useCopilotKit"; import { defineToolCallRenderer } from "../types/defineToolCallRenderer"; import type { VueToolCallRenderer, VueToolCallRendererRenderProps, } from "../types"; const EMPTY_DEPS: WatchSource[] = []; export interface RenderToolInProgressProps { name: string; toolCallId: string; parameters: Partial>; status: "inProgress"; result: undefined; } export interface RenderToolExecutingProps { name: string; toolCallId: string; parameters: InferSchemaOutput; status: "executing"; result: undefined; } export interface RenderToolCompleteProps { name: string; toolCallId: string; parameters: InferSchemaOutput; status: "complete"; result: string; } export type RenderToolProps = | RenderToolInProgressProps | RenderToolExecutingProps | RenderToolCompleteProps; type RenderToolConfig = { name: string; parameters?: S; render: | ((props: RenderToolProps) => VNodeChild) | Component>; agentId?: string; }; export function useRenderTool( config: { name: "*"; render: ((props: any) => VNodeChild) | Component; agentId?: string; }, deps?: WatchSource[], ): void; export function useRenderTool( config: { name: string; parameters: S; render: | ((props: RenderToolProps) => VNodeChild) | Component>; agentId?: string; }, deps?: WatchSource[], ): void; export function useRenderTool( config: RenderToolConfig, deps?: WatchSource[], ): void { const { copilotkit } = useCopilotKit(); const extraDeps = deps ?? EMPTY_DEPS; watch( [ () => copilotkit.value, () => config.name, () => config.agentId, () => extraDeps.length, ...extraDeps, ], () => { const renderTool = (props: RenderToolProps): VNodeChild => { if (typeof config.render === "function") { return (config.render as (props: RenderToolProps) => VNodeChild)( props, ); } return h(config.render, props); }; const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({ name: "*", render: (props: VueToolCallRendererRenderProps) => renderTool({ ...props, parameters: props.args, } as RenderToolProps), ...(config.agentId ? { agentId: config.agentId } : {}), }) : defineToolCallRenderer({ name: config.name, args: config.parameters!, render: ( props: VueToolCallRendererRenderProps>, ) => renderTool({ ...props, parameters: props.args, } as RenderToolProps), ...(config.agentId ? { agentId: config.agentId } : {}), }); copilotkit.value.addHookRenderToolCall( renderer as VueToolCallRenderer, ); // Intentionally no cleanup removal to preserve renderers for chat history. }, { immediate: true }, ); }