@copilotkitnext/react 1.54.0-next.3 → 1.54.0-next.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -66,7 +66,7 @@ function createA2UIMessageRenderer(options) {
66
66
  */
67
67
  function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
68
68
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
69
- className: "cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4",
69
+ className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
70
70
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
71
71
  onAction: (0, react.useCallback)(async (message) => {
72
72
  if (!agent) return;
@@ -1 +1 @@
1
- {"version":3,"file":"A2UIMessageRenderer.cjs","names":["z","useCopilotKit","DEFAULT_SURFACE_ID","A2UIProvider","A2UIRenderer"],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"sourcesContent":["import { useCopilotKit } from \"../providers\";\nimport type { ReactActivityMessageRenderer } from \"../types/react-activity-message-renderer\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { z } from \"zod\";\nimport {\n A2UIProvider,\n useA2UIActions,\n A2UIRenderer,\n initializeDefaultCatalog,\n injectStyles,\n DEFAULT_SURFACE_ID,\n} from \"@copilotkit/a2ui-renderer\";\nimport type { Theme, A2UIClientEventMessage } from \"@copilotkit/a2ui-renderer\";\n\n// Initialize the React renderer's component catalog and styles once\nlet initialized = false;\nfunction ensureInitialized() {\n if (!initialized) {\n initializeDefaultCatalog();\n injectStyles();\n initialized = true;\n }\n}\n\nexport type A2UIMessageRendererOptions = {\n theme: Theme;\n};\n\nexport function createA2UIMessageRenderer(\n options: A2UIMessageRendererOptions,\n): ReactActivityMessageRenderer<any> {\n const { theme } = options;\n\n return {\n activityType: \"a2ui-surface\",\n content: z.any(),\n render: ({ content, agent }) => {\n ensureInitialized();\n\n const [operations, setOperations] = useState<any[]>([]);\n const lastSignatureRef = useRef<string | null>(null);\n const { copilotkit } = useCopilotKit();\n\n useEffect(() => {\n if (!content || !Array.isArray(content.operations)) {\n lastSignatureRef.current = null;\n setOperations([]);\n return;\n }\n\n const incoming = content.operations as any[];\n const signature = stringifyOperations(incoming);\n\n if (signature && signature === lastSignatureRef.current) {\n return;\n }\n\n lastSignatureRef.current = signature;\n setOperations(incoming);\n }, [content]);\n\n // Group operations by surface ID\n const groupedOperations = useMemo(() => {\n const groups = new Map<string, any[]>();\n\n for (const operation of operations) {\n const surfaceId =\n getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;\n\n if (!groups.has(surfaceId)) {\n groups.set(surfaceId, []);\n }\n groups.get(surfaceId)!.push(operation);\n }\n\n return groups;\n }, [operations]);\n\n if (!groupedOperations.size) {\n return null;\n }\n\n return (\n <div className=\"cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6\">\n {Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => (\n <ReactSurfaceHost\n key={surfaceId}\n surfaceId={surfaceId}\n operations={ops}\n theme={theme}\n agent={agent}\n copilotkit={copilotkit}\n />\n ))}\n </div>\n );\n },\n };\n}\n\ntype ReactSurfaceHostProps = {\n surfaceId: string;\n operations: any[];\n theme: Theme;\n agent: any;\n copilotkit: any;\n};\n\n/**\n * Renders a single A2UI surface using the React renderer.\n * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.\n */\nfunction ReactSurfaceHost({\n surfaceId,\n operations,\n theme,\n agent,\n copilotkit,\n}: ReactSurfaceHostProps) {\n // Bridge: when the React renderer dispatches an action, send it to CopilotKit\n const handleAction = useCallback(\n async (message: A2UIClientEventMessage) => {\n if (!agent) return;\n\n try {\n console.info(\"[A2UI] Action dispatched\", message.userAction);\n\n copilotkit.setProperties({\n ...(copilotkit.properties ?? {}),\n a2uiAction: message,\n });\n\n await copilotkit.runAgent({ agent });\n } finally {\n if (copilotkit.properties) {\n const { a2uiAction, ...rest } = copilotkit.properties;\n copilotkit.setProperties(rest);\n }\n }\n },\n [agent, copilotkit],\n );\n\n return (\n <div className=\"cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4\">\n <A2UIProvider onAction={handleAction} theme={theme}>\n <SurfaceMessageProcessor\n surfaceId={surfaceId}\n operations={operations}\n />\n <A2UIRenderer surfaceId={surfaceId} className=\"cpk:flex cpk:flex-1\" />\n </A2UIProvider>\n </div>\n );\n}\n\n/**\n * Processes A2UI operations into the provider's message processor.\n * Must be a child of A2UIProvider to access the actions context.\n */\nfunction SurfaceMessageProcessor({\n surfaceId,\n operations,\n}: {\n surfaceId: string;\n operations: any[];\n}) {\n const { processMessages } = useA2UIActions();\n const lastProcessedRef = useRef<string>(\"\");\n\n useEffect(() => {\n const key = `${surfaceId}-${JSON.stringify(operations)}`;\n if (key === lastProcessedRef.current) return;\n lastProcessedRef.current = key;\n\n processMessages(operations);\n }, [processMessages, surfaceId, operations]);\n\n return null;\n}\n\nfunction getOperationSurfaceId(operation: any): string | null {\n if (!operation || typeof operation !== \"object\") {\n return null;\n }\n\n if (typeof operation.surfaceId === \"string\") {\n return operation.surfaceId;\n }\n\n return (\n operation?.beginRendering?.surfaceId ??\n operation?.surfaceUpdate?.surfaceId ??\n operation?.dataModelUpdate?.surfaceId ??\n operation?.deleteSurface?.surfaceId ??\n null\n );\n}\n\nfunction stringifyOperations(ops: any[]): string | null {\n try {\n return JSON.stringify(ops);\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;AAeA,IAAI,cAAc;AAClB,SAAS,oBAAoB;AAC3B,KAAI,CAAC,aAAa;AAChB,2DAA0B;AAC1B,+CAAc;AACd,gBAAc;;;AAQlB,SAAgB,0BACd,SACmC;CACnC,MAAM,EAAE,UAAU;AAElB,QAAO;EACL,cAAc;EACd,SAASA,MAAE,KAAK;EAChB,SAAS,EAAE,SAAS,YAAY;AAC9B,sBAAmB;GAEnB,MAAM,CAAC,YAAY,qCAAiC,EAAE,CAAC;GACvD,MAAM,qCAAyC,KAAK;GACpD,MAAM,EAAE,eAAeC,0CAAe;AAEtC,8BAAgB;AACd,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,WAAW,EAAE;AAClD,sBAAiB,UAAU;AAC3B,mBAAc,EAAE,CAAC;AACjB;;IAGF,MAAM,WAAW,QAAQ;IACzB,MAAM,YAAY,oBAAoB,SAAS;AAE/C,QAAI,aAAa,cAAc,iBAAiB,QAC9C;AAGF,qBAAiB,UAAU;AAC3B,kBAAc,SAAS;MACtB,CAAC,QAAQ,CAAC;GAGb,MAAM,6CAAkC;IACtC,MAAM,yBAAS,IAAI,KAAoB;AAEvC,SAAK,MAAM,aAAa,YAAY;KAClC,MAAM,YACJ,sBAAsB,UAAU,IAAIC;AAEtC,SAAI,CAAC,OAAO,IAAI,UAAU,CACxB,QAAO,IAAI,WAAW,EAAE,CAAC;AAE3B,YAAO,IAAI,UAAU,CAAE,KAAK,UAAU;;AAGxC,WAAO;MACN,CAAC,WAAW,CAAC;AAEhB,OAAI,CAAC,kBAAkB,KACrB,QAAO;AAGT,UACE,2CAAC;IAAI,WAAU;cACZ,MAAM,KAAK,kBAAkB,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,SACxD,2CAAC;KAEY;KACX,YAAY;KACL;KACA;KACK;OALP,UAML,CACF;KACE;;EAGX;;;;;;AAeH,SAAS,iBAAiB,EACxB,WACA,YACA,OACA,OACA,cACwB;AAyBxB,QACE,2CAAC;EAAI,WAAU;YACb,4CAACC;GAAa,iCAxBhB,OAAO,YAAoC;AACzC,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,aAAQ,KAAK,4BAA4B,QAAQ,WAAW;AAE5D,gBAAW,cAAc;MACvB,GAAI,WAAW,cAAc,EAAE;MAC/B,YAAY;MACb,CAAC;AAEF,WAAM,WAAW,SAAS,EAAE,OAAO,CAAC;cAC5B;AACR,SAAI,WAAW,YAAY;MACzB,MAAM,EAAE,YAAY,GAAG,SAAS,WAAW;AAC3C,iBAAW,cAAc,KAAK;;;MAIpC,CAAC,OAAO,WAAW,CACpB;GAIgD;cAC3C,2CAAC;IACY;IACC;KACZ,EACF,2CAACC;IAAwB;IAAW,WAAU;KAAwB;IACzD;GACX;;;;;;AAQV,SAAS,wBAAwB,EAC/B,WACA,cAIC;CACD,MAAM,EAAE,mEAAoC;CAC5C,MAAM,qCAAkC,GAAG;AAE3C,4BAAgB;EACd,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,UAAU,WAAW;AACtD,MAAI,QAAQ,iBAAiB,QAAS;AACtC,mBAAiB,UAAU;AAE3B,kBAAgB,WAAW;IAC1B;EAAC;EAAiB;EAAW;EAAW,CAAC;AAE5C,QAAO;;AAGT,SAAS,sBAAsB,WAA+B;AAC5D,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC,QAAO;AAGT,KAAI,OAAO,UAAU,cAAc,SACjC,QAAO,UAAU;AAGnB,QACE,WAAW,gBAAgB,aAC3B,WAAW,eAAe,aAC1B,WAAW,iBAAiB,aAC5B,WAAW,eAAe,aAC1B;;AAIJ,SAAS,oBAAoB,KAA2B;AACtD,KAAI;AACF,SAAO,KAAK,UAAU,IAAI;UACnB,OAAO;AACd,SAAO"}
1
+ {"version":3,"file":"A2UIMessageRenderer.cjs","names":["z","useCopilotKit","DEFAULT_SURFACE_ID","A2UIProvider","A2UIRenderer"],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"sourcesContent":["import { useCopilotKit } from \"../providers\";\nimport type { ReactActivityMessageRenderer } from \"../types/react-activity-message-renderer\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { z } from \"zod\";\nimport {\n A2UIProvider,\n useA2UIActions,\n A2UIRenderer,\n initializeDefaultCatalog,\n injectStyles,\n DEFAULT_SURFACE_ID,\n} from \"@copilotkit/a2ui-renderer\";\nimport type { Theme, A2UIClientEventMessage } from \"@copilotkit/a2ui-renderer\";\n\n// Initialize the React renderer's component catalog and styles once\nlet initialized = false;\nfunction ensureInitialized() {\n if (!initialized) {\n initializeDefaultCatalog();\n injectStyles();\n initialized = true;\n }\n}\n\nexport type A2UIMessageRendererOptions = {\n theme: Theme;\n};\n\nexport function createA2UIMessageRenderer(\n options: A2UIMessageRendererOptions,\n): ReactActivityMessageRenderer<any> {\n const { theme } = options;\n\n return {\n activityType: \"a2ui-surface\",\n content: z.any(),\n render: ({ content, agent }) => {\n ensureInitialized();\n\n const [operations, setOperations] = useState<any[]>([]);\n const lastSignatureRef = useRef<string | null>(null);\n const { copilotkit } = useCopilotKit();\n\n useEffect(() => {\n if (!content || !Array.isArray(content.operations)) {\n lastSignatureRef.current = null;\n setOperations([]);\n return;\n }\n\n const incoming = content.operations as any[];\n const signature = stringifyOperations(incoming);\n\n if (signature && signature === lastSignatureRef.current) {\n return;\n }\n\n lastSignatureRef.current = signature;\n setOperations(incoming);\n }, [content]);\n\n // Group operations by surface ID\n const groupedOperations = useMemo(() => {\n const groups = new Map<string, any[]>();\n\n for (const operation of operations) {\n const surfaceId =\n getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;\n\n if (!groups.has(surfaceId)) {\n groups.set(surfaceId, []);\n }\n groups.get(surfaceId)!.push(operation);\n }\n\n return groups;\n }, [operations]);\n\n if (!groupedOperations.size) {\n return null;\n }\n\n return (\n <div className=\"cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6\">\n {Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => (\n <ReactSurfaceHost\n key={surfaceId}\n surfaceId={surfaceId}\n operations={ops}\n theme={theme}\n agent={agent}\n copilotkit={copilotkit}\n />\n ))}\n </div>\n );\n },\n };\n}\n\ntype ReactSurfaceHostProps = {\n surfaceId: string;\n operations: any[];\n theme: Theme;\n agent: any;\n copilotkit: any;\n};\n\n/**\n * Renders a single A2UI surface using the React renderer.\n * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.\n */\nfunction ReactSurfaceHost({\n surfaceId,\n operations,\n theme,\n agent,\n copilotkit,\n}: ReactSurfaceHostProps) {\n // Bridge: when the React renderer dispatches an action, send it to CopilotKit\n const handleAction = useCallback(\n async (message: A2UIClientEventMessage) => {\n if (!agent) return;\n\n try {\n console.info(\"[A2UI] Action dispatched\", message.userAction);\n\n copilotkit.setProperties({\n ...(copilotkit.properties ?? {}),\n a2uiAction: message,\n });\n\n await copilotkit.runAgent({ agent });\n } finally {\n if (copilotkit.properties) {\n const { a2uiAction, ...rest } = copilotkit.properties;\n copilotkit.setProperties(rest);\n }\n }\n },\n [agent, copilotkit],\n );\n\n return (\n <div className=\"cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4\">\n <A2UIProvider onAction={handleAction} theme={theme}>\n <SurfaceMessageProcessor\n surfaceId={surfaceId}\n operations={operations}\n />\n <A2UIRenderer surfaceId={surfaceId} className=\"cpk:flex cpk:flex-1\" />\n </A2UIProvider>\n </div>\n );\n}\n\n/**\n * Processes A2UI operations into the provider's message processor.\n * Must be a child of A2UIProvider to access the actions context.\n */\nfunction SurfaceMessageProcessor({\n surfaceId,\n operations,\n}: {\n surfaceId: string;\n operations: any[];\n}) {\n const { processMessages } = useA2UIActions();\n const lastProcessedRef = useRef<string>(\"\");\n\n useEffect(() => {\n const key = `${surfaceId}-${JSON.stringify(operations)}`;\n if (key === lastProcessedRef.current) return;\n lastProcessedRef.current = key;\n\n processMessages(operations);\n }, [processMessages, surfaceId, operations]);\n\n return null;\n}\n\nfunction getOperationSurfaceId(operation: any): string | null {\n if (!operation || typeof operation !== \"object\") {\n return null;\n }\n\n if (typeof operation.surfaceId === \"string\") {\n return operation.surfaceId;\n }\n\n return (\n operation?.beginRendering?.surfaceId ??\n operation?.surfaceUpdate?.surfaceId ??\n operation?.dataModelUpdate?.surfaceId ??\n operation?.deleteSurface?.surfaceId ??\n null\n );\n}\n\nfunction stringifyOperations(ops: any[]): string | null {\n try {\n return JSON.stringify(ops);\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;AAeA,IAAI,cAAc;AAClB,SAAS,oBAAoB;AAC3B,KAAI,CAAC,aAAa;AAChB,2DAA0B;AAC1B,+CAAc;AACd,gBAAc;;;AAQlB,SAAgB,0BACd,SACmC;CACnC,MAAM,EAAE,UAAU;AAElB,QAAO;EACL,cAAc;EACd,SAASA,MAAE,KAAK;EAChB,SAAS,EAAE,SAAS,YAAY;AAC9B,sBAAmB;GAEnB,MAAM,CAAC,YAAY,qCAAiC,EAAE,CAAC;GACvD,MAAM,qCAAyC,KAAK;GACpD,MAAM,EAAE,eAAeC,0CAAe;AAEtC,8BAAgB;AACd,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,WAAW,EAAE;AAClD,sBAAiB,UAAU;AAC3B,mBAAc,EAAE,CAAC;AACjB;;IAGF,MAAM,WAAW,QAAQ;IACzB,MAAM,YAAY,oBAAoB,SAAS;AAE/C,QAAI,aAAa,cAAc,iBAAiB,QAC9C;AAGF,qBAAiB,UAAU;AAC3B,kBAAc,SAAS;MACtB,CAAC,QAAQ,CAAC;GAGb,MAAM,6CAAkC;IACtC,MAAM,yBAAS,IAAI,KAAoB;AAEvC,SAAK,MAAM,aAAa,YAAY;KAClC,MAAM,YACJ,sBAAsB,UAAU,IAAIC;AAEtC,SAAI,CAAC,OAAO,IAAI,UAAU,CACxB,QAAO,IAAI,WAAW,EAAE,CAAC;AAE3B,YAAO,IAAI,UAAU,CAAE,KAAK,UAAU;;AAGxC,WAAO;MACN,CAAC,WAAW,CAAC;AAEhB,OAAI,CAAC,kBAAkB,KACrB,QAAO;AAGT,UACE,2CAAC;IAAI,WAAU;cACZ,MAAM,KAAK,kBAAkB,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,SACxD,2CAAC;KAEY;KACX,YAAY;KACL;KACA;KACK;OALP,UAML,CACF;KACE;;EAGX;;;;;;AAeH,SAAS,iBAAiB,EACxB,WACA,YACA,OACA,OACA,cACwB;AAyBxB,QACE,2CAAC;EAAI,WAAU;YACb,4CAACC;GAAa,iCAxBhB,OAAO,YAAoC;AACzC,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,aAAQ,KAAK,4BAA4B,QAAQ,WAAW;AAE5D,gBAAW,cAAc;MACvB,GAAI,WAAW,cAAc,EAAE;MAC/B,YAAY;MACb,CAAC;AAEF,WAAM,WAAW,SAAS,EAAE,OAAO,CAAC;cAC5B;AACR,SAAI,WAAW,YAAY;MACzB,MAAM,EAAE,YAAY,GAAG,SAAS,WAAW;AAC3C,iBAAW,cAAc,KAAK;;;MAIpC,CAAC,OAAO,WAAW,CACpB;GAIgD;cAC3C,2CAAC;IACY;IACC;KACZ,EACF,2CAACC;IAAwB;IAAW,WAAU;KAAwB;IACzD;GACX;;;;;;AAQV,SAAS,wBAAwB,EAC/B,WACA,cAIC;CACD,MAAM,EAAE,mEAAoC;CAC5C,MAAM,qCAAkC,GAAG;AAE3C,4BAAgB;EACd,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,UAAU,WAAW;AACtD,MAAI,QAAQ,iBAAiB,QAAS;AACtC,mBAAiB,UAAU;AAE3B,kBAAgB,WAAW;IAC1B;EAAC;EAAiB;EAAW;EAAW,CAAC;AAE5C,QAAO;;AAGT,SAAS,sBAAsB,WAA+B;AAC5D,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC,QAAO;AAGT,KAAI,OAAO,UAAU,cAAc,SACjC,QAAO,UAAU;AAGnB,QACE,WAAW,gBAAgB,aAC3B,WAAW,eAAe,aAC1B,WAAW,iBAAiB,aAC5B,WAAW,eAAe,aAC1B;;AAIJ,SAAS,oBAAoB,KAA2B;AACtD,KAAI;AACF,SAAO,KAAK,UAAU,IAAI;UACnB,OAAO;AACd,SAAO"}
@@ -65,7 +65,7 @@ function createA2UIMessageRenderer(options) {
65
65
  */
66
66
  function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
67
67
  return /* @__PURE__ */ jsx("div", {
68
- className: "cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4",
68
+ className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
69
69
  children: /* @__PURE__ */ jsxs(A2UIProvider, {
70
70
  onAction: useCallback(async (message) => {
71
71
  if (!agent) return;
@@ -1 +1 @@
1
- {"version":3,"file":"A2UIMessageRenderer.mjs","names":[],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"sourcesContent":["import { useCopilotKit } from \"../providers\";\nimport type { ReactActivityMessageRenderer } from \"../types/react-activity-message-renderer\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { z } from \"zod\";\nimport {\n A2UIProvider,\n useA2UIActions,\n A2UIRenderer,\n initializeDefaultCatalog,\n injectStyles,\n DEFAULT_SURFACE_ID,\n} from \"@copilotkit/a2ui-renderer\";\nimport type { Theme, A2UIClientEventMessage } from \"@copilotkit/a2ui-renderer\";\n\n// Initialize the React renderer's component catalog and styles once\nlet initialized = false;\nfunction ensureInitialized() {\n if (!initialized) {\n initializeDefaultCatalog();\n injectStyles();\n initialized = true;\n }\n}\n\nexport type A2UIMessageRendererOptions = {\n theme: Theme;\n};\n\nexport function createA2UIMessageRenderer(\n options: A2UIMessageRendererOptions,\n): ReactActivityMessageRenderer<any> {\n const { theme } = options;\n\n return {\n activityType: \"a2ui-surface\",\n content: z.any(),\n render: ({ content, agent }) => {\n ensureInitialized();\n\n const [operations, setOperations] = useState<any[]>([]);\n const lastSignatureRef = useRef<string | null>(null);\n const { copilotkit } = useCopilotKit();\n\n useEffect(() => {\n if (!content || !Array.isArray(content.operations)) {\n lastSignatureRef.current = null;\n setOperations([]);\n return;\n }\n\n const incoming = content.operations as any[];\n const signature = stringifyOperations(incoming);\n\n if (signature && signature === lastSignatureRef.current) {\n return;\n }\n\n lastSignatureRef.current = signature;\n setOperations(incoming);\n }, [content]);\n\n // Group operations by surface ID\n const groupedOperations = useMemo(() => {\n const groups = new Map<string, any[]>();\n\n for (const operation of operations) {\n const surfaceId =\n getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;\n\n if (!groups.has(surfaceId)) {\n groups.set(surfaceId, []);\n }\n groups.get(surfaceId)!.push(operation);\n }\n\n return groups;\n }, [operations]);\n\n if (!groupedOperations.size) {\n return null;\n }\n\n return (\n <div className=\"cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6\">\n {Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => (\n <ReactSurfaceHost\n key={surfaceId}\n surfaceId={surfaceId}\n operations={ops}\n theme={theme}\n agent={agent}\n copilotkit={copilotkit}\n />\n ))}\n </div>\n );\n },\n };\n}\n\ntype ReactSurfaceHostProps = {\n surfaceId: string;\n operations: any[];\n theme: Theme;\n agent: any;\n copilotkit: any;\n};\n\n/**\n * Renders a single A2UI surface using the React renderer.\n * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.\n */\nfunction ReactSurfaceHost({\n surfaceId,\n operations,\n theme,\n agent,\n copilotkit,\n}: ReactSurfaceHostProps) {\n // Bridge: when the React renderer dispatches an action, send it to CopilotKit\n const handleAction = useCallback(\n async (message: A2UIClientEventMessage) => {\n if (!agent) return;\n\n try {\n console.info(\"[A2UI] Action dispatched\", message.userAction);\n\n copilotkit.setProperties({\n ...(copilotkit.properties ?? {}),\n a2uiAction: message,\n });\n\n await copilotkit.runAgent({ agent });\n } finally {\n if (copilotkit.properties) {\n const { a2uiAction, ...rest } = copilotkit.properties;\n copilotkit.setProperties(rest);\n }\n }\n },\n [agent, copilotkit],\n );\n\n return (\n <div className=\"cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4\">\n <A2UIProvider onAction={handleAction} theme={theme}>\n <SurfaceMessageProcessor\n surfaceId={surfaceId}\n operations={operations}\n />\n <A2UIRenderer surfaceId={surfaceId} className=\"cpk:flex cpk:flex-1\" />\n </A2UIProvider>\n </div>\n );\n}\n\n/**\n * Processes A2UI operations into the provider's message processor.\n * Must be a child of A2UIProvider to access the actions context.\n */\nfunction SurfaceMessageProcessor({\n surfaceId,\n operations,\n}: {\n surfaceId: string;\n operations: any[];\n}) {\n const { processMessages } = useA2UIActions();\n const lastProcessedRef = useRef<string>(\"\");\n\n useEffect(() => {\n const key = `${surfaceId}-${JSON.stringify(operations)}`;\n if (key === lastProcessedRef.current) return;\n lastProcessedRef.current = key;\n\n processMessages(operations);\n }, [processMessages, surfaceId, operations]);\n\n return null;\n}\n\nfunction getOperationSurfaceId(operation: any): string | null {\n if (!operation || typeof operation !== \"object\") {\n return null;\n }\n\n if (typeof operation.surfaceId === \"string\") {\n return operation.surfaceId;\n }\n\n return (\n operation?.beginRendering?.surfaceId ??\n operation?.surfaceUpdate?.surfaceId ??\n operation?.dataModelUpdate?.surfaceId ??\n operation?.deleteSurface?.surfaceId ??\n null\n );\n}\n\nfunction stringifyOperations(ops: any[]): string | null {\n try {\n return JSON.stringify(ops);\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;AAeA,IAAI,cAAc;AAClB,SAAS,oBAAoB;AAC3B,KAAI,CAAC,aAAa;AAChB,4BAA0B;AAC1B,gBAAc;AACd,gBAAc;;;AAQlB,SAAgB,0BACd,SACmC;CACnC,MAAM,EAAE,UAAU;AAElB,QAAO;EACL,cAAc;EACd,SAAS,EAAE,KAAK;EAChB,SAAS,EAAE,SAAS,YAAY;AAC9B,sBAAmB;GAEnB,MAAM,CAAC,YAAY,iBAAiB,SAAgB,EAAE,CAAC;GACvD,MAAM,mBAAmB,OAAsB,KAAK;GACpD,MAAM,EAAE,eAAe,eAAe;AAEtC,mBAAgB;AACd,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,WAAW,EAAE;AAClD,sBAAiB,UAAU;AAC3B,mBAAc,EAAE,CAAC;AACjB;;IAGF,MAAM,WAAW,QAAQ;IACzB,MAAM,YAAY,oBAAoB,SAAS;AAE/C,QAAI,aAAa,cAAc,iBAAiB,QAC9C;AAGF,qBAAiB,UAAU;AAC3B,kBAAc,SAAS;MACtB,CAAC,QAAQ,CAAC;GAGb,MAAM,oBAAoB,cAAc;IACtC,MAAM,yBAAS,IAAI,KAAoB;AAEvC,SAAK,MAAM,aAAa,YAAY;KAClC,MAAM,YACJ,sBAAsB,UAAU,IAAI;AAEtC,SAAI,CAAC,OAAO,IAAI,UAAU,CACxB,QAAO,IAAI,WAAW,EAAE,CAAC;AAE3B,YAAO,IAAI,UAAU,CAAE,KAAK,UAAU;;AAGxC,WAAO;MACN,CAAC,WAAW,CAAC;AAEhB,OAAI,CAAC,kBAAkB,KACrB,QAAO;AAGT,UACE,oBAAC;IAAI,WAAU;cACZ,MAAM,KAAK,kBAAkB,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,SACxD,oBAAC;KAEY;KACX,YAAY;KACL;KACA;KACK;OALP,UAML,CACF;KACE;;EAGX;;;;;;AAeH,SAAS,iBAAiB,EACxB,WACA,YACA,OACA,OACA,cACwB;AAyBxB,QACE,oBAAC;EAAI,WAAU;YACb,qBAAC;GAAa,UAzBG,YACnB,OAAO,YAAoC;AACzC,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,aAAQ,KAAK,4BAA4B,QAAQ,WAAW;AAE5D,gBAAW,cAAc;MACvB,GAAI,WAAW,cAAc,EAAE;MAC/B,YAAY;MACb,CAAC;AAEF,WAAM,WAAW,SAAS,EAAE,OAAO,CAAC;cAC5B;AACR,SAAI,WAAW,YAAY;MACzB,MAAM,EAAE,YAAY,GAAG,SAAS,WAAW;AAC3C,iBAAW,cAAc,KAAK;;;MAIpC,CAAC,OAAO,WAAW,CACpB;GAIgD;cAC3C,oBAAC;IACY;IACC;KACZ,EACF,oBAAC;IAAwB;IAAW,WAAU;KAAwB;IACzD;GACX;;;;;;AAQV,SAAS,wBAAwB,EAC/B,WACA,cAIC;CACD,MAAM,EAAE,oBAAoB,gBAAgB;CAC5C,MAAM,mBAAmB,OAAe,GAAG;AAE3C,iBAAgB;EACd,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,UAAU,WAAW;AACtD,MAAI,QAAQ,iBAAiB,QAAS;AACtC,mBAAiB,UAAU;AAE3B,kBAAgB,WAAW;IAC1B;EAAC;EAAiB;EAAW;EAAW,CAAC;AAE5C,QAAO;;AAGT,SAAS,sBAAsB,WAA+B;AAC5D,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC,QAAO;AAGT,KAAI,OAAO,UAAU,cAAc,SACjC,QAAO,UAAU;AAGnB,QACE,WAAW,gBAAgB,aAC3B,WAAW,eAAe,aAC1B,WAAW,iBAAiB,aAC5B,WAAW,eAAe,aAC1B;;AAIJ,SAAS,oBAAoB,KAA2B;AACtD,KAAI;AACF,SAAO,KAAK,UAAU,IAAI;UACnB,OAAO;AACd,SAAO"}
1
+ {"version":3,"file":"A2UIMessageRenderer.mjs","names":[],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"sourcesContent":["import { useCopilotKit } from \"../providers\";\nimport type { ReactActivityMessageRenderer } from \"../types/react-activity-message-renderer\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { z } from \"zod\";\nimport {\n A2UIProvider,\n useA2UIActions,\n A2UIRenderer,\n initializeDefaultCatalog,\n injectStyles,\n DEFAULT_SURFACE_ID,\n} from \"@copilotkit/a2ui-renderer\";\nimport type { Theme, A2UIClientEventMessage } from \"@copilotkit/a2ui-renderer\";\n\n// Initialize the React renderer's component catalog and styles once\nlet initialized = false;\nfunction ensureInitialized() {\n if (!initialized) {\n initializeDefaultCatalog();\n injectStyles();\n initialized = true;\n }\n}\n\nexport type A2UIMessageRendererOptions = {\n theme: Theme;\n};\n\nexport function createA2UIMessageRenderer(\n options: A2UIMessageRendererOptions,\n): ReactActivityMessageRenderer<any> {\n const { theme } = options;\n\n return {\n activityType: \"a2ui-surface\",\n content: z.any(),\n render: ({ content, agent }) => {\n ensureInitialized();\n\n const [operations, setOperations] = useState<any[]>([]);\n const lastSignatureRef = useRef<string | null>(null);\n const { copilotkit } = useCopilotKit();\n\n useEffect(() => {\n if (!content || !Array.isArray(content.operations)) {\n lastSignatureRef.current = null;\n setOperations([]);\n return;\n }\n\n const incoming = content.operations as any[];\n const signature = stringifyOperations(incoming);\n\n if (signature && signature === lastSignatureRef.current) {\n return;\n }\n\n lastSignatureRef.current = signature;\n setOperations(incoming);\n }, [content]);\n\n // Group operations by surface ID\n const groupedOperations = useMemo(() => {\n const groups = new Map<string, any[]>();\n\n for (const operation of operations) {\n const surfaceId =\n getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;\n\n if (!groups.has(surfaceId)) {\n groups.set(surfaceId, []);\n }\n groups.get(surfaceId)!.push(operation);\n }\n\n return groups;\n }, [operations]);\n\n if (!groupedOperations.size) {\n return null;\n }\n\n return (\n <div className=\"cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6\">\n {Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => (\n <ReactSurfaceHost\n key={surfaceId}\n surfaceId={surfaceId}\n operations={ops}\n theme={theme}\n agent={agent}\n copilotkit={copilotkit}\n />\n ))}\n </div>\n );\n },\n };\n}\n\ntype ReactSurfaceHostProps = {\n surfaceId: string;\n operations: any[];\n theme: Theme;\n agent: any;\n copilotkit: any;\n};\n\n/**\n * Renders a single A2UI surface using the React renderer.\n * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.\n */\nfunction ReactSurfaceHost({\n surfaceId,\n operations,\n theme,\n agent,\n copilotkit,\n}: ReactSurfaceHostProps) {\n // Bridge: when the React renderer dispatches an action, send it to CopilotKit\n const handleAction = useCallback(\n async (message: A2UIClientEventMessage) => {\n if (!agent) return;\n\n try {\n console.info(\"[A2UI] Action dispatched\", message.userAction);\n\n copilotkit.setProperties({\n ...(copilotkit.properties ?? {}),\n a2uiAction: message,\n });\n\n await copilotkit.runAgent({ agent });\n } finally {\n if (copilotkit.properties) {\n const { a2uiAction, ...rest } = copilotkit.properties;\n copilotkit.setProperties(rest);\n }\n }\n },\n [agent, copilotkit],\n );\n\n return (\n <div className=\"cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4\">\n <A2UIProvider onAction={handleAction} theme={theme}>\n <SurfaceMessageProcessor\n surfaceId={surfaceId}\n operations={operations}\n />\n <A2UIRenderer surfaceId={surfaceId} className=\"cpk:flex cpk:flex-1\" />\n </A2UIProvider>\n </div>\n );\n}\n\n/**\n * Processes A2UI operations into the provider's message processor.\n * Must be a child of A2UIProvider to access the actions context.\n */\nfunction SurfaceMessageProcessor({\n surfaceId,\n operations,\n}: {\n surfaceId: string;\n operations: any[];\n}) {\n const { processMessages } = useA2UIActions();\n const lastProcessedRef = useRef<string>(\"\");\n\n useEffect(() => {\n const key = `${surfaceId}-${JSON.stringify(operations)}`;\n if (key === lastProcessedRef.current) return;\n lastProcessedRef.current = key;\n\n processMessages(operations);\n }, [processMessages, surfaceId, operations]);\n\n return null;\n}\n\nfunction getOperationSurfaceId(operation: any): string | null {\n if (!operation || typeof operation !== \"object\") {\n return null;\n }\n\n if (typeof operation.surfaceId === \"string\") {\n return operation.surfaceId;\n }\n\n return (\n operation?.beginRendering?.surfaceId ??\n operation?.surfaceUpdate?.surfaceId ??\n operation?.dataModelUpdate?.surfaceId ??\n operation?.deleteSurface?.surfaceId ??\n null\n );\n}\n\nfunction stringifyOperations(ops: any[]): string | null {\n try {\n return JSON.stringify(ops);\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;AAeA,IAAI,cAAc;AAClB,SAAS,oBAAoB;AAC3B,KAAI,CAAC,aAAa;AAChB,4BAA0B;AAC1B,gBAAc;AACd,gBAAc;;;AAQlB,SAAgB,0BACd,SACmC;CACnC,MAAM,EAAE,UAAU;AAElB,QAAO;EACL,cAAc;EACd,SAAS,EAAE,KAAK;EAChB,SAAS,EAAE,SAAS,YAAY;AAC9B,sBAAmB;GAEnB,MAAM,CAAC,YAAY,iBAAiB,SAAgB,EAAE,CAAC;GACvD,MAAM,mBAAmB,OAAsB,KAAK;GACpD,MAAM,EAAE,eAAe,eAAe;AAEtC,mBAAgB;AACd,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,WAAW,EAAE;AAClD,sBAAiB,UAAU;AAC3B,mBAAc,EAAE,CAAC;AACjB;;IAGF,MAAM,WAAW,QAAQ;IACzB,MAAM,YAAY,oBAAoB,SAAS;AAE/C,QAAI,aAAa,cAAc,iBAAiB,QAC9C;AAGF,qBAAiB,UAAU;AAC3B,kBAAc,SAAS;MACtB,CAAC,QAAQ,CAAC;GAGb,MAAM,oBAAoB,cAAc;IACtC,MAAM,yBAAS,IAAI,KAAoB;AAEvC,SAAK,MAAM,aAAa,YAAY;KAClC,MAAM,YACJ,sBAAsB,UAAU,IAAI;AAEtC,SAAI,CAAC,OAAO,IAAI,UAAU,CACxB,QAAO,IAAI,WAAW,EAAE,CAAC;AAE3B,YAAO,IAAI,UAAU,CAAE,KAAK,UAAU;;AAGxC,WAAO;MACN,CAAC,WAAW,CAAC;AAEhB,OAAI,CAAC,kBAAkB,KACrB,QAAO;AAGT,UACE,oBAAC;IAAI,WAAU;cACZ,MAAM,KAAK,kBAAkB,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,SACxD,oBAAC;KAEY;KACX,YAAY;KACL;KACA;KACK;OALP,UAML,CACF;KACE;;EAGX;;;;;;AAeH,SAAS,iBAAiB,EACxB,WACA,YACA,OACA,OACA,cACwB;AAyBxB,QACE,oBAAC;EAAI,WAAU;YACb,qBAAC;GAAa,UAzBG,YACnB,OAAO,YAAoC;AACzC,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,aAAQ,KAAK,4BAA4B,QAAQ,WAAW;AAE5D,gBAAW,cAAc;MACvB,GAAI,WAAW,cAAc,EAAE;MAC/B,YAAY;MACb,CAAC;AAEF,WAAM,WAAW,SAAS,EAAE,OAAO,CAAC;cAC5B;AACR,SAAI,WAAW,YAAY;MACzB,MAAM,EAAE,YAAY,GAAG,SAAS,WAAW;AAC3C,iBAAW,cAAc,KAAK;;;MAIpC,CAAC,OAAO,WAAW,CACpB;GAIgD;cAC3C,oBAAC;IACY;IACC;KACZ,EACF,oBAAC;IAAwB;IAAW,WAAU;KAAwB;IACzD;GACX;;;;;;AAQV,SAAS,wBAAwB,EAC/B,WACA,cAIC;CACD,MAAM,EAAE,oBAAoB,gBAAgB;CAC5C,MAAM,mBAAmB,OAAe,GAAG;AAE3C,iBAAgB;EACd,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,UAAU,WAAW;AACtD,MAAI,QAAQ,iBAAiB,QAAS;AACtC,mBAAiB,UAAU;AAE3B,kBAAgB,WAAW;IAC1B;EAAC;EAAiB;EAAW;EAAW,CAAC;AAE5C,QAAO;;AAGT,SAAS,sBAAsB,WAA+B;AAC5D,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC,QAAO;AAGT,KAAI,OAAO,UAAU,cAAc,SACjC,QAAO,UAAU;AAGnB,QACE,WAAW,gBAAgB,aAC3B,WAAW,eAAe,aAC1B,WAAW,iBAAiB,aAC5B,WAAW,eAAe,aAC1B;;AAIJ,SAAS,oBAAoB,KAA2B;AACtD,KAAI;AACF,SAAO,KAAK,UAAU,IAAI;UACnB,OAAO;AACd,SAAO"}
@@ -17,20 +17,12 @@ function useFrontendTool(tool, deps) {
17
17
  copilotkit.removeTool(name, tool.agentId);
18
18
  }
19
19
  copilotkit.addTool(tool);
20
- if (tool.render) {
21
- const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
22
- const currentRenderToolCalls = copilotkit.renderToolCalls;
23
- const mergedMap = /* @__PURE__ */ new Map();
24
- for (const rc of currentRenderToolCalls) mergedMap.set(keyOf(rc), rc);
25
- const newEntry = {
26
- name,
27
- args: tool.parameters,
28
- agentId: tool.agentId,
29
- render: tool.render
30
- };
31
- mergedMap.set(keyOf(newEntry), newEntry);
32
- copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
33
- }
20
+ if (tool.render && tool.parameters) copilotkit.addHookRenderToolCall({
21
+ name,
22
+ args: tool.parameters,
23
+ agentId: tool.agentId,
24
+ render: tool.render
25
+ });
34
26
  return () => {
35
27
  copilotkit.removeTool(name, tool.agentId);
36
28
  };
@@ -1 +1 @@
1
- {"version":3,"file":"use-frontend-tool.cjs","names":["useCopilotKit"],"sources":["../../src/hooks/use-frontend-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport function useFrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactFrontendTool<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n const name = tool.name;\n\n // Always register/override the tool for this name on mount\n if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {\n console.warn(\n `Tool '${name}' already exists for agent '${tool.agentId || \"global\"}'. Overriding with latest registration.`,\n );\n copilotkit.removeTool(name, tool.agentId);\n }\n copilotkit.addTool(tool);\n\n // Register/override renderer by name and agentId through core\n if (tool.render) {\n // Get current render tool calls and merge with new entry\n const keyOf = (rc: ReactToolCallRenderer) =>\n `${rc.agentId ?? \"\"}:${rc.name}`;\n const currentRenderToolCalls =\n copilotkit.renderToolCalls as ReactToolCallRenderer[];\n\n // Build map from existing entries\n const mergedMap = new Map<string, ReactToolCallRenderer>();\n for (const rc of currentRenderToolCalls) {\n mergedMap.set(keyOf(rc), rc);\n }\n\n // Add/overwrite with new entry\n const newEntry: ReactToolCallRenderer = {\n name,\n args: tool.parameters,\n agentId: tool.agentId,\n render: tool.render,\n } as ReactToolCallRenderer;\n mergedMap.set(keyOf(newEntry), newEntry);\n\n // Set the merged list back\n copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));\n }\n\n return () => {\n copilotkit.removeTool(name, tool.agentId);\n // we are intentionally not removing the render here so that the tools can still render in the chat history\n };\n // Depend on stable keys by default and allow callers to opt into\n // additional dependencies for dynamic tool configuration.\n // tool.available is included so toggling availability re-registers the tool.\n }, [tool.name, tool.available, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;;AAKA,MAAM,aAAqC,EAAE;AAE7C,SAAgB,gBAEd,MAA4B,MAA+B;CAC3D,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,4BAAgB;EACd,MAAM,OAAO,KAAK;AAGlB,MAAI,WAAW,QAAQ;GAAE,UAAU;GAAM,SAAS,KAAK;GAAS,CAAC,EAAE;AACjE,WAAQ,KACN,SAAS,KAAK,8BAA8B,KAAK,WAAW,SAAS,yCACtE;AACD,cAAW,WAAW,MAAM,KAAK,QAAQ;;AAE3C,aAAW,QAAQ,KAAK;AAGxB,MAAI,KAAK,QAAQ;GAEf,MAAM,SAAS,OACb,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG;GAC5B,MAAM,yBACJ,WAAW;GAGb,MAAM,4BAAY,IAAI,KAAoC;AAC1D,QAAK,MAAM,MAAM,uBACf,WAAU,IAAI,MAAM,GAAG,EAAE,GAAG;GAI9B,MAAM,WAAkC;IACtC;IACA,MAAM,KAAK;IACX,SAAS,KAAK;IACd,QAAQ,KAAK;IACd;AACD,aAAU,IAAI,MAAM,SAAS,EAAE,SAAS;AAGxC,cAAW,mBAAmB,MAAM,KAAK,UAAU,QAAQ,CAAC,CAAC;;AAG/D,eAAa;AACX,cAAW,WAAW,MAAM,KAAK,QAAQ;;IAM1C;EAAC,KAAK;EAAM,KAAK;EAAW;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
1
+ {"version":3,"file":"use-frontend-tool.cjs","names":["useCopilotKit"],"sources":["../../src/hooks/use-frontend-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport function useFrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactFrontendTool<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n const name = tool.name;\n\n // Always register/override the tool for this name on mount\n if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {\n console.warn(\n `Tool '${name}' already exists for agent '${tool.agentId || \"global\"}'. Overriding with latest registration.`,\n );\n copilotkit.removeTool(name, tool.agentId);\n }\n copilotkit.addTool(tool);\n\n // Register/override renderer by name and agentId through core\n if (tool.render && tool.parameters) {\n copilotkit.addHookRenderToolCall({\n name,\n args: tool.parameters,\n agentId: tool.agentId,\n render: tool.render,\n });\n }\n\n return () => {\n copilotkit.removeTool(name, tool.agentId);\n // we are intentionally not removing the render here so that the tools can still render in the chat history\n };\n // Depend on stable keys by default and allow callers to opt into\n // additional dependencies for dynamic tool configuration.\n // tool.available is included so toggling availability re-registers the tool.\n }, [tool.name, tool.available, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;;AAIA,MAAM,aAAqC,EAAE;AAE7C,SAAgB,gBAEd,MAA4B,MAA+B;CAC3D,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,4BAAgB;EACd,MAAM,OAAO,KAAK;AAGlB,MAAI,WAAW,QAAQ;GAAE,UAAU;GAAM,SAAS,KAAK;GAAS,CAAC,EAAE;AACjE,WAAQ,KACN,SAAS,KAAK,8BAA8B,KAAK,WAAW,SAAS,yCACtE;AACD,cAAW,WAAW,MAAM,KAAK,QAAQ;;AAE3C,aAAW,QAAQ,KAAK;AAGxB,MAAI,KAAK,UAAU,KAAK,WACtB,YAAW,sBAAsB;GAC/B;GACA,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACd,CAAC;AAGJ,eAAa;AACX,cAAW,WAAW,MAAM,KAAK,QAAQ;;IAM1C;EAAC,KAAK;EAAM,KAAK;EAAW;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-frontend-tool.d.cts","names":[],"sources":["../../src/hooks/use-frontend-tool.tsx"],"mappings":";;;iBAOgB,eAAA,WACJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,IAAA,EAAM,iBAAA,CAAkB,CAAA,GAAI,IAAA,GAAO,aAAA"}
1
+ {"version":3,"file":"use-frontend-tool.d.cts","names":[],"sources":["../../src/hooks/use-frontend-tool.tsx"],"mappings":";;;iBAMgB,eAAA,WACJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,IAAA,EAAM,iBAAA,CAAkB,CAAA,GAAI,IAAA,GAAO,aAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-frontend-tool.d.mts","names":[],"sources":["../../src/hooks/use-frontend-tool.tsx"],"mappings":";;;iBAOgB,eAAA,WACJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,IAAA,EAAM,iBAAA,CAAkB,CAAA,GAAI,IAAA,GAAO,aAAA"}
1
+ {"version":3,"file":"use-frontend-tool.d.mts","names":[],"sources":["../../src/hooks/use-frontend-tool.tsx"],"mappings":";;;iBAMgB,eAAA,WACJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,IAAA,EAAM,iBAAA,CAAkB,CAAA,GAAI,IAAA,GAAO,aAAA"}
@@ -16,20 +16,12 @@ function useFrontendTool(tool, deps) {
16
16
  copilotkit.removeTool(name, tool.agentId);
17
17
  }
18
18
  copilotkit.addTool(tool);
19
- if (tool.render) {
20
- const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
21
- const currentRenderToolCalls = copilotkit.renderToolCalls;
22
- const mergedMap = /* @__PURE__ */ new Map();
23
- for (const rc of currentRenderToolCalls) mergedMap.set(keyOf(rc), rc);
24
- const newEntry = {
25
- name,
26
- args: tool.parameters,
27
- agentId: tool.agentId,
28
- render: tool.render
29
- };
30
- mergedMap.set(keyOf(newEntry), newEntry);
31
- copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
32
- }
19
+ if (tool.render && tool.parameters) copilotkit.addHookRenderToolCall({
20
+ name,
21
+ args: tool.parameters,
22
+ agentId: tool.agentId,
23
+ render: tool.render
24
+ });
33
25
  return () => {
34
26
  copilotkit.removeTool(name, tool.agentId);
35
27
  };
@@ -1 +1 @@
1
- {"version":3,"file":"use-frontend-tool.mjs","names":[],"sources":["../../src/hooks/use-frontend-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport function useFrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactFrontendTool<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n const name = tool.name;\n\n // Always register/override the tool for this name on mount\n if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {\n console.warn(\n `Tool '${name}' already exists for agent '${tool.agentId || \"global\"}'. Overriding with latest registration.`,\n );\n copilotkit.removeTool(name, tool.agentId);\n }\n copilotkit.addTool(tool);\n\n // Register/override renderer by name and agentId through core\n if (tool.render) {\n // Get current render tool calls and merge with new entry\n const keyOf = (rc: ReactToolCallRenderer) =>\n `${rc.agentId ?? \"\"}:${rc.name}`;\n const currentRenderToolCalls =\n copilotkit.renderToolCalls as ReactToolCallRenderer[];\n\n // Build map from existing entries\n const mergedMap = new Map<string, ReactToolCallRenderer>();\n for (const rc of currentRenderToolCalls) {\n mergedMap.set(keyOf(rc), rc);\n }\n\n // Add/overwrite with new entry\n const newEntry: ReactToolCallRenderer = {\n name,\n args: tool.parameters,\n agentId: tool.agentId,\n render: tool.render,\n } as ReactToolCallRenderer;\n mergedMap.set(keyOf(newEntry), newEntry);\n\n // Set the merged list back\n copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));\n }\n\n return () => {\n copilotkit.removeTool(name, tool.agentId);\n // we are intentionally not removing the render here so that the tools can still render in the chat history\n };\n // Depend on stable keys by default and allow callers to opt into\n // additional dependencies for dynamic tool configuration.\n // tool.available is included so toggling availability re-registers the tool.\n }, [tool.name, tool.available, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;AAKA,MAAM,aAAqC,EAAE;AAE7C,SAAgB,gBAEd,MAA4B,MAA+B;CAC3D,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,iBAAgB;EACd,MAAM,OAAO,KAAK;AAGlB,MAAI,WAAW,QAAQ;GAAE,UAAU;GAAM,SAAS,KAAK;GAAS,CAAC,EAAE;AACjE,WAAQ,KACN,SAAS,KAAK,8BAA8B,KAAK,WAAW,SAAS,yCACtE;AACD,cAAW,WAAW,MAAM,KAAK,QAAQ;;AAE3C,aAAW,QAAQ,KAAK;AAGxB,MAAI,KAAK,QAAQ;GAEf,MAAM,SAAS,OACb,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG;GAC5B,MAAM,yBACJ,WAAW;GAGb,MAAM,4BAAY,IAAI,KAAoC;AAC1D,QAAK,MAAM,MAAM,uBACf,WAAU,IAAI,MAAM,GAAG,EAAE,GAAG;GAI9B,MAAM,WAAkC;IACtC;IACA,MAAM,KAAK;IACX,SAAS,KAAK;IACd,QAAQ,KAAK;IACd;AACD,aAAU,IAAI,MAAM,SAAS,EAAE,SAAS;AAGxC,cAAW,mBAAmB,MAAM,KAAK,UAAU,QAAQ,CAAC,CAAC;;AAG/D,eAAa;AACX,cAAW,WAAW,MAAM,KAAK,QAAQ;;IAM1C;EAAC,KAAK;EAAM,KAAK;EAAW;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
1
+ {"version":3,"file":"use-frontend-tool.mjs","names":[],"sources":["../../src/hooks/use-frontend-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"../types/frontend-tool\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport function useFrontendTool<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactFrontendTool<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n const name = tool.name;\n\n // Always register/override the tool for this name on mount\n if (copilotkit.getTool({ toolName: name, agentId: tool.agentId })) {\n console.warn(\n `Tool '${name}' already exists for agent '${tool.agentId || \"global\"}'. Overriding with latest registration.`,\n );\n copilotkit.removeTool(name, tool.agentId);\n }\n copilotkit.addTool(tool);\n\n // Register/override renderer by name and agentId through core\n if (tool.render && tool.parameters) {\n copilotkit.addHookRenderToolCall({\n name,\n args: tool.parameters,\n agentId: tool.agentId,\n render: tool.render,\n });\n }\n\n return () => {\n copilotkit.removeTool(name, tool.agentId);\n // we are intentionally not removing the render here so that the tools can still render in the chat history\n };\n // Depend on stable keys by default and allow callers to opt into\n // additional dependencies for dynamic tool configuration.\n // tool.available is included so toggling availability re-registers the tool.\n }, [tool.name, tool.available, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;AAIA,MAAM,aAAqC,EAAE;AAE7C,SAAgB,gBAEd,MAA4B,MAA+B;CAC3D,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,iBAAgB;EACd,MAAM,OAAO,KAAK;AAGlB,MAAI,WAAW,QAAQ;GAAE,UAAU;GAAM,SAAS,KAAK;GAAS,CAAC,EAAE;AACjE,WAAQ,KACN,SAAS,KAAK,8BAA8B,KAAK,WAAW,SAAS,yCACtE;AACD,cAAW,WAAW,MAAM,KAAK,QAAQ;;AAE3C,aAAW,QAAQ,KAAK;AAGxB,MAAI,KAAK,UAAU,KAAK,WACtB,YAAW,sBAAsB;GAC/B;GACA,MAAM,KAAK;GACX,SAAS,KAAK;GACd,QAAQ,KAAK;GACd,CAAC;AAGJ,eAAa;AACX,cAAW,WAAW,MAAM,KAAK,QAAQ;;IAM1C;EAAC,KAAK;EAAM,KAAK;EAAW;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
@@ -60,12 +60,7 @@ function useHumanInTheLoop(tool, deps) {
60
60
  }, deps);
61
61
  (0, react.useEffect)(() => {
62
62
  return () => {
63
- const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
64
- const filtered = copilotkit.renderToolCalls.filter((rc) => keyOf(rc) !== keyOf({
65
- name: tool.name,
66
- agentId: tool.agentId
67
- }));
68
- copilotkit.setRenderToolCalls(filtered);
63
+ copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);
69
64
  };
70
65
  }, [
71
66
  copilotkit,
@@ -1 +1 @@
1
- {"version":3,"file":"use-human-in-the-loop.cjs","names":["useCopilotKit","React"],"sources":["../../src/hooks/use-human-in-the-loop.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"@/types/frontend-tool\";\nimport type { ReactHumanInTheLoop } from \"@/types/human-in-the-loop\";\nimport type { ReactToolCallRenderer } from \"@/types/react-tool-call-renderer\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport React from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\nexport function useHumanInTheLoop<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactHumanInTheLoop<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const resolvePromiseRef = useRef<((result: unknown) => void) | null>(null);\n\n const respond = useCallback(async (result: unknown) => {\n if (resolvePromiseRef.current) {\n resolvePromiseRef.current(result);\n resolvePromiseRef.current = null;\n }\n }, []);\n\n const handler = useCallback(async () => {\n return new Promise((resolve) => {\n resolvePromiseRef.current = resolve;\n });\n }, []);\n\n const RenderComponent: ReactToolCallRenderer<T>[\"render\"] = useCallback(\n (props) => {\n const ToolComponent = tool.render;\n\n // Enhance props based on current status\n if (props.status === \"inProgress\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"executing\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"complete\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n }\n\n // Fallback - just render with original props\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.createElement(ToolComponent, props as any);\n },\n [tool.render, tool.name, tool.description, respond],\n );\n\n const frontendTool: ReactFrontendTool<T> = {\n ...tool,\n handler,\n render: RenderComponent,\n };\n\n useFrontendTool(frontendTool, deps);\n\n // Human-in-the-loop tools should remove their renderer on unmount\n // since they can't respond to user interactions anymore\n useEffect(() => {\n return () => {\n const keyOf = (rc: ReactToolCallRenderer<any>) =>\n `${rc.agentId ?? \"\"}:${rc.name}`;\n const currentRenderToolCalls =\n copilotkit.renderToolCalls as ReactToolCallRenderer<any>[];\n const filtered = currentRenderToolCalls.filter(\n (rc) =>\n keyOf(rc) !==\n keyOf({ name: tool.name, agentId: tool.agentId } as any),\n );\n copilotkit.setRenderToolCalls(filtered);\n };\n }, [copilotkit, tool.name, tool.agentId]);\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,kBAEd,MAA8B,MAA+B;CAC7D,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,sCAA+D,KAAK;CAE1E,MAAM,iCAAsB,OAAO,WAAoB;AACrD,MAAI,kBAAkB,SAAS;AAC7B,qBAAkB,QAAQ,OAAO;AACjC,qBAAkB,UAAU;;IAE7B,EAAE,CAAC;CAEN,MAAM,iCAAsB,YAAY;AACtC,SAAO,IAAI,SAAS,YAAY;AAC9B,qBAAkB,UAAU;IAC5B;IACD,EAAE,CAAC;CAEN,MAAM,0CACH,UAAU;EACT,MAAM,gBAAgB,KAAK;AAG3B,MAAI,MAAM,WAAW,cAAc;GACjC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAOC,cAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,aAAa;GACvC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC;IACD;AACD,UAAOA,cAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,YAAY;GACtC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAOA,cAAM,cAAc,eAAe,cAAc;;AAK1D,SAAOA,cAAM,cAAc,eAAe,MAAa;IAEzD;EAAC,KAAK;EAAQ,KAAK;EAAM,KAAK;EAAa;EAAQ,CACpD;AAQD,2CAN2C;EACzC,GAAG;EACH;EACA,QAAQ;EACT,EAE6B,KAAK;AAInC,4BAAgB;AACd,eAAa;GACX,MAAM,SAAS,OACb,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG;GAG5B,MAAM,WADJ,WAAW,gBAC2B,QACrC,OACC,MAAM,GAAG,KACT,MAAM;IAAE,MAAM,KAAK;IAAM,SAAS,KAAK;IAAS,CAAQ,CAC3D;AACD,cAAW,mBAAmB,SAAS;;IAExC;EAAC;EAAY,KAAK;EAAM,KAAK;EAAQ,CAAC"}
1
+ {"version":3,"file":"use-human-in-the-loop.cjs","names":["useCopilotKit","React"],"sources":["../../src/hooks/use-human-in-the-loop.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"@/types/frontend-tool\";\nimport type { ReactHumanInTheLoop } from \"@/types/human-in-the-loop\";\nimport type { ReactToolCallRenderer } from \"@/types/react-tool-call-renderer\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport React from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\nexport function useHumanInTheLoop<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactHumanInTheLoop<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const resolvePromiseRef = useRef<((result: unknown) => void) | null>(null);\n\n const respond = useCallback(async (result: unknown) => {\n if (resolvePromiseRef.current) {\n resolvePromiseRef.current(result);\n resolvePromiseRef.current = null;\n }\n }, []);\n\n const handler = useCallback(async () => {\n return new Promise((resolve) => {\n resolvePromiseRef.current = resolve;\n });\n }, []);\n\n const RenderComponent: ReactToolCallRenderer<T>[\"render\"] = useCallback(\n (props) => {\n const ToolComponent = tool.render;\n\n // Enhance props based on current status\n if (props.status === \"inProgress\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"executing\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"complete\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n }\n\n // Fallback - just render with original props\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.createElement(ToolComponent, props as any);\n },\n [tool.render, tool.name, tool.description, respond],\n );\n\n const frontendTool: ReactFrontendTool<T> = {\n ...tool,\n handler,\n render: RenderComponent,\n };\n\n useFrontendTool(frontendTool, deps);\n\n // Human-in-the-loop tools should remove their renderer on unmount\n // since they can't respond to user interactions anymore\n useEffect(() => {\n return () => {\n copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);\n };\n }, [copilotkit, tool.name, tool.agentId]);\n}\n"],"mappings":";;;;;;;AAQA,SAAgB,kBAEd,MAA8B,MAA+B;CAC7D,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,sCAA+D,KAAK;CAE1E,MAAM,iCAAsB,OAAO,WAAoB;AACrD,MAAI,kBAAkB,SAAS;AAC7B,qBAAkB,QAAQ,OAAO;AACjC,qBAAkB,UAAU;;IAE7B,EAAE,CAAC;CAEN,MAAM,iCAAsB,YAAY;AACtC,SAAO,IAAI,SAAS,YAAY;AAC9B,qBAAkB,UAAU;IAC5B;IACD,EAAE,CAAC;CAEN,MAAM,0CACH,UAAU;EACT,MAAM,gBAAgB,KAAK;AAG3B,MAAI,MAAM,WAAW,cAAc;GACjC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAOC,cAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,aAAa;GACvC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC;IACD;AACD,UAAOA,cAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,YAAY;GACtC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAOA,cAAM,cAAc,eAAe,cAAc;;AAK1D,SAAOA,cAAM,cAAc,eAAe,MAAa;IAEzD;EAAC,KAAK;EAAQ,KAAK;EAAM,KAAK;EAAa;EAAQ,CACpD;AAQD,2CAN2C;EACzC,GAAG;EACH;EACA,QAAQ;EACT,EAE6B,KAAK;AAInC,4BAAgB;AACd,eAAa;AACX,cAAW,yBAAyB,KAAK,MAAM,KAAK,QAAQ;;IAE7D;EAAC;EAAY,KAAK;EAAM,KAAK;EAAQ,CAAC"}
@@ -58,12 +58,7 @@ function useHumanInTheLoop(tool, deps) {
58
58
  }, deps);
59
59
  useEffect(() => {
60
60
  return () => {
61
- const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
62
- const filtered = copilotkit.renderToolCalls.filter((rc) => keyOf(rc) !== keyOf({
63
- name: tool.name,
64
- agentId: tool.agentId
65
- }));
66
- copilotkit.setRenderToolCalls(filtered);
61
+ copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);
67
62
  };
68
63
  }, [
69
64
  copilotkit,
@@ -1 +1 @@
1
- {"version":3,"file":"use-human-in-the-loop.mjs","names":[],"sources":["../../src/hooks/use-human-in-the-loop.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"@/types/frontend-tool\";\nimport type { ReactHumanInTheLoop } from \"@/types/human-in-the-loop\";\nimport type { ReactToolCallRenderer } from \"@/types/react-tool-call-renderer\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport React from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\nexport function useHumanInTheLoop<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactHumanInTheLoop<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const resolvePromiseRef = useRef<((result: unknown) => void) | null>(null);\n\n const respond = useCallback(async (result: unknown) => {\n if (resolvePromiseRef.current) {\n resolvePromiseRef.current(result);\n resolvePromiseRef.current = null;\n }\n }, []);\n\n const handler = useCallback(async () => {\n return new Promise((resolve) => {\n resolvePromiseRef.current = resolve;\n });\n }, []);\n\n const RenderComponent: ReactToolCallRenderer<T>[\"render\"] = useCallback(\n (props) => {\n const ToolComponent = tool.render;\n\n // Enhance props based on current status\n if (props.status === \"inProgress\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"executing\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"complete\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n }\n\n // Fallback - just render with original props\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.createElement(ToolComponent, props as any);\n },\n [tool.render, tool.name, tool.description, respond],\n );\n\n const frontendTool: ReactFrontendTool<T> = {\n ...tool,\n handler,\n render: RenderComponent,\n };\n\n useFrontendTool(frontendTool, deps);\n\n // Human-in-the-loop tools should remove their renderer on unmount\n // since they can't respond to user interactions anymore\n useEffect(() => {\n return () => {\n const keyOf = (rc: ReactToolCallRenderer<any>) =>\n `${rc.agentId ?? \"\"}:${rc.name}`;\n const currentRenderToolCalls =\n copilotkit.renderToolCalls as ReactToolCallRenderer<any>[];\n const filtered = currentRenderToolCalls.filter(\n (rc) =>\n keyOf(rc) !==\n keyOf({ name: tool.name, agentId: tool.agentId } as any),\n );\n copilotkit.setRenderToolCalls(filtered);\n };\n }, [copilotkit, tool.name, tool.agentId]);\n}\n"],"mappings":";;;;;AAQA,SAAgB,kBAEd,MAA8B,MAA+B;CAC7D,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,oBAAoB,OAA2C,KAAK;CAE1E,MAAM,UAAU,YAAY,OAAO,WAAoB;AACrD,MAAI,kBAAkB,SAAS;AAC7B,qBAAkB,QAAQ,OAAO;AACjC,qBAAkB,UAAU;;IAE7B,EAAE,CAAC;CAEN,MAAM,UAAU,YAAY,YAAY;AACtC,SAAO,IAAI,SAAS,YAAY;AAC9B,qBAAkB,UAAU;IAC5B;IACD,EAAE,CAAC;CAEN,MAAM,kBAAsD,aACzD,UAAU;EACT,MAAM,gBAAgB,KAAK;AAG3B,MAAI,MAAM,WAAW,cAAc;GACjC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,aAAa;GACvC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC;IACD;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,YAAY;GACtC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;;AAK1D,SAAO,MAAM,cAAc,eAAe,MAAa;IAEzD;EAAC,KAAK;EAAQ,KAAK;EAAM,KAAK;EAAa;EAAQ,CACpD;AAQD,iBAN2C;EACzC,GAAG;EACH;EACA,QAAQ;EACT,EAE6B,KAAK;AAInC,iBAAgB;AACd,eAAa;GACX,MAAM,SAAS,OACb,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG;GAG5B,MAAM,WADJ,WAAW,gBAC2B,QACrC,OACC,MAAM,GAAG,KACT,MAAM;IAAE,MAAM,KAAK;IAAM,SAAS,KAAK;IAAS,CAAQ,CAC3D;AACD,cAAW,mBAAmB,SAAS;;IAExC;EAAC;EAAY,KAAK;EAAM,KAAK;EAAQ,CAAC"}
1
+ {"version":3,"file":"use-human-in-the-loop.mjs","names":[],"sources":["../../src/hooks/use-human-in-the-loop.tsx"],"sourcesContent":["import { useCopilotKit } from \"@/providers/CopilotKitProvider\";\nimport type { ReactFrontendTool } from \"@/types/frontend-tool\";\nimport type { ReactHumanInTheLoop } from \"@/types/human-in-the-loop\";\nimport type { ReactToolCallRenderer } from \"@/types/react-tool-call-renderer\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport React from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\nexport function useHumanInTheLoop<\n T extends Record<string, unknown> = Record<string, unknown>,\n>(tool: ReactHumanInTheLoop<T>, deps?: ReadonlyArray<unknown>) {\n const { copilotkit } = useCopilotKit();\n const resolvePromiseRef = useRef<((result: unknown) => void) | null>(null);\n\n const respond = useCallback(async (result: unknown) => {\n if (resolvePromiseRef.current) {\n resolvePromiseRef.current(result);\n resolvePromiseRef.current = null;\n }\n }, []);\n\n const handler = useCallback(async () => {\n return new Promise((resolve) => {\n resolvePromiseRef.current = resolve;\n });\n }, []);\n\n const RenderComponent: ReactToolCallRenderer<T>[\"render\"] = useCallback(\n (props) => {\n const ToolComponent = tool.render;\n\n // Enhance props based on current status\n if (props.status === \"inProgress\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"executing\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond,\n };\n return React.createElement(ToolComponent, enhancedProps);\n } else if (props.status === \"complete\") {\n const enhancedProps = {\n ...props,\n name: tool.name,\n description: tool.description || \"\",\n respond: undefined,\n };\n return React.createElement(ToolComponent, enhancedProps);\n }\n\n // Fallback - just render with original props\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return React.createElement(ToolComponent, props as any);\n },\n [tool.render, tool.name, tool.description, respond],\n );\n\n const frontendTool: ReactFrontendTool<T> = {\n ...tool,\n handler,\n render: RenderComponent,\n };\n\n useFrontendTool(frontendTool, deps);\n\n // Human-in-the-loop tools should remove their renderer on unmount\n // since they can't respond to user interactions anymore\n useEffect(() => {\n return () => {\n copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);\n };\n }, [copilotkit, tool.name, tool.agentId]);\n}\n"],"mappings":";;;;;AAQA,SAAgB,kBAEd,MAA8B,MAA+B;CAC7D,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,oBAAoB,OAA2C,KAAK;CAE1E,MAAM,UAAU,YAAY,OAAO,WAAoB;AACrD,MAAI,kBAAkB,SAAS;AAC7B,qBAAkB,QAAQ,OAAO;AACjC,qBAAkB,UAAU;;IAE7B,EAAE,CAAC;CAEN,MAAM,UAAU,YAAY,YAAY;AACtC,SAAO,IAAI,SAAS,YAAY;AAC9B,qBAAkB,UAAU;IAC5B;IACD,EAAE,CAAC;CAEN,MAAM,kBAAsD,aACzD,UAAU;EACT,MAAM,gBAAgB,KAAK;AAG3B,MAAI,MAAM,WAAW,cAAc;GACjC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,aAAa;GACvC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC;IACD;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;aAC/C,MAAM,WAAW,YAAY;GACtC,MAAM,gBAAgB;IACpB,GAAG;IACH,MAAM,KAAK;IACX,aAAa,KAAK,eAAe;IACjC,SAAS;IACV;AACD,UAAO,MAAM,cAAc,eAAe,cAAc;;AAK1D,SAAO,MAAM,cAAc,eAAe,MAAa;IAEzD;EAAC,KAAK;EAAQ,KAAK;EAAM,KAAK;EAAa;EAAQ,CACpD;AAQD,iBAN2C;EACzC,GAAG;EACH;EACA,QAAQ;EACT,EAE6B,KAAK;AAInC,iBAAgB;AACd,eAAa;AACX,cAAW,yBAAyB,KAAK,MAAM,KAAK,QAAQ;;IAE7D;EAAC;EAAY,KAAK;EAAM,KAAK;EAAQ,CAAC"}
@@ -66,12 +66,7 @@ function useRenderTool(config, deps) {
66
66
  }),
67
67
  ...config.agentId ? { agentId: config.agentId } : {}
68
68
  });
69
- const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
70
- const currentRenderToolCalls = copilotkit.renderToolCalls;
71
- const mergedMap = /* @__PURE__ */ new Map();
72
- for (const rc of currentRenderToolCalls) mergedMap.set(keyOf(rc), rc);
73
- mergedMap.set(keyOf(renderer), renderer);
74
- copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
69
+ copilotkit.addHookRenderToolCall(renderer);
75
70
  }, [
76
71
  config.name,
77
72
  copilotkit,
@@ -1 +1 @@
1
- {"version":3,"file":"use-render-tool.cjs","names":["useCopilotKit","defineToolCallRenderer"],"sources":["../../src/hooks/use-render-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport type {\n StandardSchemaV1,\n InferSchemaOutput,\n} from \"@copilotkitnext/shared\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport { defineToolCallRenderer } from \"../types/defineToolCallRenderer\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport interface RenderToolInProgressProps<S extends StandardSchemaV1> {\n name: string;\n parameters: Partial<InferSchemaOutput<S>>;\n status: \"inProgress\";\n result: undefined;\n}\n\nexport interface RenderToolExecutingProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"executing\";\n result: undefined;\n}\n\nexport interface RenderToolCompleteProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"complete\";\n result: string;\n}\n\nexport type RenderToolProps<S extends StandardSchemaV1> =\n | RenderToolInProgressProps<S>\n | RenderToolExecutingProps<S>\n | RenderToolCompleteProps<S>;\n\ntype RenderToolConfig<S extends StandardSchemaV1> = {\n name: string;\n parameters?: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n};\n\n/**\n * Registers a wildcard (`\"*\"`) renderer for tool calls.\n *\n * The wildcard renderer is used as a fallback when no exact name-matched\n * renderer is registered for a tool call.\n *\n * @param config - Wildcard renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"*\",\n * render: ({ name, status }) => (\n * <div>\n * {status === \"complete\" ? \"✓\" : \"⏳\"} {name}\n * </div>\n * ),\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool(\n config: {\n name: \"*\";\n render: (props: any) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a name-scoped renderer for tool calls.\n *\n * The provided `parameters` schema defines the typed shape of `props.parameters`\n * in `render` for `executing` and `complete` states. Accepts any Standard Schema V1\n * compatible library (Zod, Valibot, ArkType, etc.).\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Named renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"inProgress\") return <div>Preparing...</div>;\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * return <div>{result}</div>;\n * },\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: {\n name: string;\n parameters: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.\n *\n * Key behavior:\n * - deduplicates by `agentId:name` (latest registration wins),\n * - keeps renderer entries on cleanup so historical chat tool calls can still render,\n * - refreshes registration when `deps` change.\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Renderer config for wildcard or named tools.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * if (status === \"complete\") return <div>{result}</div>;\n * return <div>Preparing...</div>;\n * },\n * },\n * [],\n * );\n * ```\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"summarize\",\n * parameters: z.object({ text: z.string() }),\n * agentId: \"research-agent\",\n * render: ({ name, status }) => <div>{name}: {status}</div>,\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: RenderToolConfig<S>,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n // Build the ReactToolCallRenderer via defineToolCallRenderer\n const renderer =\n config.name === \"*\" && !config.parameters\n ? defineToolCallRenderer({\n name: \"*\",\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n })\n : defineToolCallRenderer({\n name: config.name,\n args: config.parameters!,\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n });\n\n // Dedupe by \"agentId:name\" key, same pattern as useFrontendTool\n const keyOf = (rc: ReactToolCallRenderer) =>\n `${rc.agentId ?? \"\"}:${rc.name}`;\n const currentRenderToolCalls =\n copilotkit.renderToolCalls as ReactToolCallRenderer[];\n\n const mergedMap = new Map<string, ReactToolCallRenderer>();\n for (const rc of currentRenderToolCalls) {\n mergedMap.set(keyOf(rc), rc);\n }\n\n mergedMap.set(keyOf(renderer), renderer);\n\n copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));\n\n // No cleanup removal — keeps renderer for chat history, same as useFrontendTool\n }, [config.name, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;;;AASA,MAAM,aAAqC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkJ7C,SAAgB,cACd,QACA,MACM;CACN,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,4BAAgB;EAEd,MAAM,WACJ,OAAO,SAAS,OAAO,CAAC,OAAO,aAC3BC,sDAAuB;GACrB,MAAM;GACN,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC,GACFA,sDAAuB;GACrB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC;EAGR,MAAM,SAAS,OACb,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG;EAC5B,MAAM,yBACJ,WAAW;EAEb,MAAM,4BAAY,IAAI,KAAoC;AAC1D,OAAK,MAAM,MAAM,uBACf,WAAU,IAAI,MAAM,GAAG,EAAE,GAAG;AAG9B,YAAU,IAAI,MAAM,SAAS,EAAE,SAAS;AAExC,aAAW,mBAAmB,MAAM,KAAK,UAAU,QAAQ,CAAC,CAAC;IAG5D;EAAC,OAAO;EAAM;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
1
+ {"version":3,"file":"use-render-tool.cjs","names":["useCopilotKit","defineToolCallRenderer"],"sources":["../../src/hooks/use-render-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport type {\n StandardSchemaV1,\n InferSchemaOutput,\n} from \"@copilotkitnext/shared\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport { defineToolCallRenderer } from \"../types/defineToolCallRenderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport interface RenderToolInProgressProps<S extends StandardSchemaV1> {\n name: string;\n parameters: Partial<InferSchemaOutput<S>>;\n status: \"inProgress\";\n result: undefined;\n}\n\nexport interface RenderToolExecutingProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"executing\";\n result: undefined;\n}\n\nexport interface RenderToolCompleteProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"complete\";\n result: string;\n}\n\nexport type RenderToolProps<S extends StandardSchemaV1> =\n | RenderToolInProgressProps<S>\n | RenderToolExecutingProps<S>\n | RenderToolCompleteProps<S>;\n\ntype RenderToolConfig<S extends StandardSchemaV1> = {\n name: string;\n parameters?: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n};\n\n/**\n * Registers a wildcard (`\"*\"`) renderer for tool calls.\n *\n * The wildcard renderer is used as a fallback when no exact name-matched\n * renderer is registered for a tool call.\n *\n * @param config - Wildcard renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"*\",\n * render: ({ name, status }) => (\n * <div>\n * {status === \"complete\" ? \"✓\" : \"⏳\"} {name}\n * </div>\n * ),\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool(\n config: {\n name: \"*\";\n render: (props: any) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a name-scoped renderer for tool calls.\n *\n * The provided `parameters` schema defines the typed shape of `props.parameters`\n * in `render` for `executing` and `complete` states. Accepts any Standard Schema V1\n * compatible library (Zod, Valibot, ArkType, etc.).\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Named renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"inProgress\") return <div>Preparing...</div>;\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * return <div>{result}</div>;\n * },\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: {\n name: string;\n parameters: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.\n *\n * Key behavior:\n * - deduplicates by `agentId:name` (latest registration wins),\n * - keeps renderer entries on cleanup so historical chat tool calls can still render,\n * - refreshes registration when `deps` change.\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Renderer config for wildcard or named tools.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * if (status === \"complete\") return <div>{result}</div>;\n * return <div>Preparing...</div>;\n * },\n * },\n * [],\n * );\n * ```\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"summarize\",\n * parameters: z.object({ text: z.string() }),\n * agentId: \"research-agent\",\n * render: ({ name, status }) => <div>{name}: {status}</div>,\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: RenderToolConfig<S>,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n // Build the ReactToolCallRenderer via defineToolCallRenderer\n const renderer =\n config.name === \"*\" && !config.parameters\n ? defineToolCallRenderer({\n name: \"*\",\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n })\n : defineToolCallRenderer({\n name: config.name,\n args: config.parameters!,\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n });\n\n copilotkit.addHookRenderToolCall(renderer);\n\n // No cleanup removal — keeps renderer for chat history, same as useFrontendTool\n }, [config.name, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;;;AAQA,MAAM,aAAqC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkJ7C,SAAgB,cACd,QACA,MACM;CACN,MAAM,EAAE,eAAeA,0CAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,4BAAgB;EAEd,MAAM,WACJ,OAAO,SAAS,OAAO,CAAC,OAAO,aAC3BC,sDAAuB;GACrB,MAAM;GACN,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC,GACFA,sDAAuB;GACrB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC;AAER,aAAW,sBAAsB,SAAS;IAGzC;EAAC,OAAO;EAAM;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-render-tool.d.cts","names":[],"sources":["../../src/hooks/use-render-tool.tsx"],"mappings":";;;UAWiB,yBAAA,WAAoC,gBAAA;EACnD,IAAA;EACA,UAAA,EAAY,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EACtC,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,wBAAA,WAAmC,gBAAA;EAClD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,uBAAA,WAAkC,gBAAA;EACjD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,KAGU,eAAA,WAA0B,gBAAA,IAClC,yBAAA,CAA0B,CAAA,IAC1B,wBAAA,CAAyB,CAAA,IACzB,uBAAA,CAAwB,CAAA;;;;AAjB5B;;;;;;;;;;;;;;;;;;AAOA;;;iBA2CgB,aAAA,CACd,MAAA;EACE,IAAA;EACA,MAAA,GAAS,KAAA,UAAe,KAAA,CAAM,YAAA;EAC9B,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA;;;;;;;;;;;AA1CT;;;;;;;;;;;;;;;;;iBAwEgB,aAAA,WAAwB,gBAAA,CAAA,CACtC,MAAA;EACE,IAAA;EACA,UAAA,EAAY,CAAA;EACZ,MAAA,GAAS,KAAA,EAAO,eAAA,CAAgB,CAAA,MAAO,KAAA,CAAM,YAAA;EAC7C,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA"}
1
+ {"version":3,"file":"use-render-tool.d.cts","names":[],"sources":["../../src/hooks/use-render-tool.tsx"],"mappings":";;;UAUiB,yBAAA,WAAoC,gBAAA;EACnD,IAAA;EACA,UAAA,EAAY,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EACtC,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,wBAAA,WAAmC,gBAAA;EAClD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,uBAAA,WAAkC,gBAAA;EACjD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,KAGU,eAAA,WAA0B,gBAAA,IAClC,yBAAA,CAA0B,CAAA,IAC1B,wBAAA,CAAyB,CAAA,IACzB,uBAAA,CAAwB,CAAA;;;;AAjB5B;;;;;;;;;;;;;;;;;;AAOA;;;iBA2CgB,aAAA,CACd,MAAA;EACE,IAAA;EACA,MAAA,GAAS,KAAA,UAAe,KAAA,CAAM,YAAA;EAC9B,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA;;;;;;;;;;;AA1CT;;;;;;;;;;;;;;;;;iBAwEgB,aAAA,WAAwB,gBAAA,CAAA,CACtC,MAAA;EACE,IAAA;EACA,UAAA,EAAY,CAAA;EACZ,MAAA,GAAS,KAAA,EAAO,eAAA,CAAgB,CAAA,MAAO,KAAA,CAAM,YAAA;EAC7C,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-render-tool.d.mts","names":[],"sources":["../../src/hooks/use-render-tool.tsx"],"mappings":";;;UAWiB,yBAAA,WAAoC,gBAAA;EACnD,IAAA;EACA,UAAA,EAAY,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EACtC,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,wBAAA,WAAmC,gBAAA;EAClD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,uBAAA,WAAkC,gBAAA;EACjD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,KAGU,eAAA,WAA0B,gBAAA,IAClC,yBAAA,CAA0B,CAAA,IAC1B,wBAAA,CAAyB,CAAA,IACzB,uBAAA,CAAwB,CAAA;;;;AAjB5B;;;;;;;;;;;;;;;;;;AAOA;;;iBA2CgB,aAAA,CACd,MAAA;EACE,IAAA;EACA,MAAA,GAAS,KAAA,UAAe,KAAA,CAAM,YAAA;EAC9B,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA;;;;;;;;;;;AA1CT;;;;;;;;;;;;;;;;;iBAwEgB,aAAA,WAAwB,gBAAA,CAAA,CACtC,MAAA;EACE,IAAA;EACA,UAAA,EAAY,CAAA;EACZ,MAAA,GAAS,KAAA,EAAO,eAAA,CAAgB,CAAA,MAAO,KAAA,CAAM,YAAA;EAC7C,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA"}
1
+ {"version":3,"file":"use-render-tool.d.mts","names":[],"sources":["../../src/hooks/use-render-tool.tsx"],"mappings":";;;UAUiB,yBAAA,WAAoC,gBAAA;EACnD,IAAA;EACA,UAAA,EAAY,OAAA,CAAQ,iBAAA,CAAkB,CAAA;EACtC,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,wBAAA,WAAmC,gBAAA;EAClD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,UAGe,uBAAA,WAAkC,gBAAA;EACjD,IAAA;EACA,UAAA,EAAY,iBAAA,CAAkB,CAAA;EAC9B,MAAA;EACA,MAAA;AAAA;AAAA,KAGU,eAAA,WAA0B,gBAAA,IAClC,yBAAA,CAA0B,CAAA,IAC1B,wBAAA,CAAyB,CAAA,IACzB,uBAAA,CAAwB,CAAA;;;;AAjB5B;;;;;;;;;;;;;;;;;;AAOA;;;iBA2CgB,aAAA,CACd,MAAA;EACE,IAAA;EACA,MAAA,GAAS,KAAA,UAAe,KAAA,CAAM,YAAA;EAC9B,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA;;;;;;;;;;;AA1CT;;;;;;;;;;;;;;;;;iBAwEgB,aAAA,WAAwB,gBAAA,CAAA,CACtC,MAAA;EACE,IAAA;EACA,UAAA,EAAY,CAAA;EACZ,MAAA,GAAS,KAAA,EAAO,eAAA,CAAgB,CAAA,MAAO,KAAA,CAAM,YAAA;EAC7C,OAAA;AAAA,GAEF,IAAA,GAAO,aAAA"}
@@ -65,12 +65,7 @@ function useRenderTool(config, deps) {
65
65
  }),
66
66
  ...config.agentId ? { agentId: config.agentId } : {}
67
67
  });
68
- const keyOf = (rc) => `${rc.agentId ?? ""}:${rc.name}`;
69
- const currentRenderToolCalls = copilotkit.renderToolCalls;
70
- const mergedMap = /* @__PURE__ */ new Map();
71
- for (const rc of currentRenderToolCalls) mergedMap.set(keyOf(rc), rc);
72
- mergedMap.set(keyOf(renderer), renderer);
73
- copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
68
+ copilotkit.addHookRenderToolCall(renderer);
74
69
  }, [
75
70
  config.name,
76
71
  copilotkit,
@@ -1 +1 @@
1
- {"version":3,"file":"use-render-tool.mjs","names":[],"sources":["../../src/hooks/use-render-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport type {\n StandardSchemaV1,\n InferSchemaOutput,\n} from \"@copilotkitnext/shared\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport { defineToolCallRenderer } from \"../types/defineToolCallRenderer\";\nimport type { ReactToolCallRenderer } from \"../types/react-tool-call-renderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport interface RenderToolInProgressProps<S extends StandardSchemaV1> {\n name: string;\n parameters: Partial<InferSchemaOutput<S>>;\n status: \"inProgress\";\n result: undefined;\n}\n\nexport interface RenderToolExecutingProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"executing\";\n result: undefined;\n}\n\nexport interface RenderToolCompleteProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"complete\";\n result: string;\n}\n\nexport type RenderToolProps<S extends StandardSchemaV1> =\n | RenderToolInProgressProps<S>\n | RenderToolExecutingProps<S>\n | RenderToolCompleteProps<S>;\n\ntype RenderToolConfig<S extends StandardSchemaV1> = {\n name: string;\n parameters?: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n};\n\n/**\n * Registers a wildcard (`\"*\"`) renderer for tool calls.\n *\n * The wildcard renderer is used as a fallback when no exact name-matched\n * renderer is registered for a tool call.\n *\n * @param config - Wildcard renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"*\",\n * render: ({ name, status }) => (\n * <div>\n * {status === \"complete\" ? \"✓\" : \"⏳\"} {name}\n * </div>\n * ),\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool(\n config: {\n name: \"*\";\n render: (props: any) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a name-scoped renderer for tool calls.\n *\n * The provided `parameters` schema defines the typed shape of `props.parameters`\n * in `render` for `executing` and `complete` states. Accepts any Standard Schema V1\n * compatible library (Zod, Valibot, ArkType, etc.).\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Named renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"inProgress\") return <div>Preparing...</div>;\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * return <div>{result}</div>;\n * },\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: {\n name: string;\n parameters: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.\n *\n * Key behavior:\n * - deduplicates by `agentId:name` (latest registration wins),\n * - keeps renderer entries on cleanup so historical chat tool calls can still render,\n * - refreshes registration when `deps` change.\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Renderer config for wildcard or named tools.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * if (status === \"complete\") return <div>{result}</div>;\n * return <div>Preparing...</div>;\n * },\n * },\n * [],\n * );\n * ```\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"summarize\",\n * parameters: z.object({ text: z.string() }),\n * agentId: \"research-agent\",\n * render: ({ name, status }) => <div>{name}: {status}</div>,\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: RenderToolConfig<S>,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n // Build the ReactToolCallRenderer via defineToolCallRenderer\n const renderer =\n config.name === \"*\" && !config.parameters\n ? defineToolCallRenderer({\n name: \"*\",\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n })\n : defineToolCallRenderer({\n name: config.name,\n args: config.parameters!,\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n });\n\n // Dedupe by \"agentId:name\" key, same pattern as useFrontendTool\n const keyOf = (rc: ReactToolCallRenderer) =>\n `${rc.agentId ?? \"\"}:${rc.name}`;\n const currentRenderToolCalls =\n copilotkit.renderToolCalls as ReactToolCallRenderer[];\n\n const mergedMap = new Map<string, ReactToolCallRenderer>();\n for (const rc of currentRenderToolCalls) {\n mergedMap.set(keyOf(rc), rc);\n }\n\n mergedMap.set(keyOf(renderer), renderer);\n\n copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));\n\n // No cleanup removal — keeps renderer for chat history, same as useFrontendTool\n }, [config.name, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;;AASA,MAAM,aAAqC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkJ7C,SAAgB,cACd,QACA,MACM;CACN,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,iBAAgB;EAEd,MAAM,WACJ,OAAO,SAAS,OAAO,CAAC,OAAO,aAC3B,uBAAuB;GACrB,MAAM;GACN,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC,GACF,uBAAuB;GACrB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC;EAGR,MAAM,SAAS,OACb,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG;EAC5B,MAAM,yBACJ,WAAW;EAEb,MAAM,4BAAY,IAAI,KAAoC;AAC1D,OAAK,MAAM,MAAM,uBACf,WAAU,IAAI,MAAM,GAAG,EAAE,GAAG;AAG9B,YAAU,IAAI,MAAM,SAAS,EAAE,SAAS;AAExC,aAAW,mBAAmB,MAAM,KAAK,UAAU,QAAQ,CAAC,CAAC;IAG5D;EAAC,OAAO;EAAM;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
1
+ {"version":3,"file":"use-render-tool.mjs","names":[],"sources":["../../src/hooks/use-render-tool.tsx"],"sourcesContent":["import { useEffect } from \"react\";\nimport type {\n StandardSchemaV1,\n InferSchemaOutput,\n} from \"@copilotkitnext/shared\";\nimport { useCopilotKit } from \"../providers/CopilotKitProvider\";\nimport { defineToolCallRenderer } from \"../types/defineToolCallRenderer\";\n\nconst EMPTY_DEPS: ReadonlyArray<unknown> = [];\n\nexport interface RenderToolInProgressProps<S extends StandardSchemaV1> {\n name: string;\n parameters: Partial<InferSchemaOutput<S>>;\n status: \"inProgress\";\n result: undefined;\n}\n\nexport interface RenderToolExecutingProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"executing\";\n result: undefined;\n}\n\nexport interface RenderToolCompleteProps<S extends StandardSchemaV1> {\n name: string;\n parameters: InferSchemaOutput<S>;\n status: \"complete\";\n result: string;\n}\n\nexport type RenderToolProps<S extends StandardSchemaV1> =\n | RenderToolInProgressProps<S>\n | RenderToolExecutingProps<S>\n | RenderToolCompleteProps<S>;\n\ntype RenderToolConfig<S extends StandardSchemaV1> = {\n name: string;\n parameters?: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n};\n\n/**\n * Registers a wildcard (`\"*\"`) renderer for tool calls.\n *\n * The wildcard renderer is used as a fallback when no exact name-matched\n * renderer is registered for a tool call.\n *\n * @param config - Wildcard renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"*\",\n * render: ({ name, status }) => (\n * <div>\n * {status === \"complete\" ? \"✓\" : \"⏳\"} {name}\n * </div>\n * ),\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool(\n config: {\n name: \"*\";\n render: (props: any) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a name-scoped renderer for tool calls.\n *\n * The provided `parameters` schema defines the typed shape of `props.parameters`\n * in `render` for `executing` and `complete` states. Accepts any Standard Schema V1\n * compatible library (Zod, Valibot, ArkType, etc.).\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Named renderer configuration.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"inProgress\") return <div>Preparing...</div>;\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * return <div>{result}</div>;\n * },\n * },\n * [],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: {\n name: string;\n parameters: S;\n render: (props: RenderToolProps<S>) => React.ReactElement;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void;\n\n/**\n * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.\n *\n * Key behavior:\n * - deduplicates by `agentId:name` (latest registration wins),\n * - keeps renderer entries on cleanup so historical chat tool calls can still render,\n * - refreshes registration when `deps` change.\n *\n * @typeParam S - Schema type describing tool call parameters.\n * @param config - Renderer config for wildcard or named tools.\n * @param deps - Optional dependencies to refresh registration.\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"searchDocs\",\n * parameters: z.object({ query: z.string() }),\n * render: ({ status, parameters, result }) => {\n * if (status === \"executing\") return <div>Searching {parameters.query}</div>;\n * if (status === \"complete\") return <div>{result}</div>;\n * return <div>Preparing...</div>;\n * },\n * },\n * [],\n * );\n * ```\n *\n * @example\n * ```tsx\n * useRenderTool(\n * {\n * name: \"summarize\",\n * parameters: z.object({ text: z.string() }),\n * agentId: \"research-agent\",\n * render: ({ name, status }) => <div>{name}: {status}</div>,\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useRenderTool<S extends StandardSchemaV1>(\n config: RenderToolConfig<S>,\n deps?: ReadonlyArray<unknown>,\n): void {\n const { copilotkit } = useCopilotKit();\n const extraDeps = deps ?? EMPTY_DEPS;\n\n useEffect(() => {\n // Build the ReactToolCallRenderer via defineToolCallRenderer\n const renderer =\n config.name === \"*\" && !config.parameters\n ? defineToolCallRenderer({\n name: \"*\",\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n })\n : defineToolCallRenderer({\n name: config.name,\n args: config.parameters!,\n render: (props) =>\n config.render({ ...props, parameters: props.args }),\n ...(config.agentId ? { agentId: config.agentId } : {}),\n });\n\n copilotkit.addHookRenderToolCall(renderer);\n\n // No cleanup removal — keeps renderer for chat history, same as useFrontendTool\n }, [config.name, copilotkit, extraDeps.length, ...extraDeps]);\n}\n"],"mappings":";;;;;AAQA,MAAM,aAAqC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkJ7C,SAAgB,cACd,QACA,MACM;CACN,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,YAAY,QAAQ;AAE1B,iBAAgB;EAEd,MAAM,WACJ,OAAO,SAAS,OAAO,CAAC,OAAO,aAC3B,uBAAuB;GACrB,MAAM;GACN,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC,GACF,uBAAuB;GACrB,MAAM,OAAO;GACb,MAAM,OAAO;GACb,SAAS,UACP,OAAO,OAAO;IAAE,GAAG;IAAO,YAAY,MAAM;IAAM,CAAC;GACrD,GAAI,OAAO,UAAU,EAAE,SAAS,OAAO,SAAS,GAAG,EAAE;GACtD,CAAC;AAER,aAAW,sBAAsB,SAAS;IAGzC;EAAC,OAAO;EAAM;EAAY,UAAU;EAAQ,GAAG;EAAU,CAAC"}
package/dist/index.umd.js CHANGED
@@ -1873,7 +1873,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1873
1873
  */
1874
1874
  function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
1875
1875
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1876
- className: "cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4",
1876
+ className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
1877
1877
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
1878
1878
  onAction: (0, react.useCallback)(async (message) => {
1879
1879
  if (!agent) return;
@@ -1943,6 +1943,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1943
1943
  var _config$renderToolCal, _config$renderCustomM, _config$renderActivit;
1944
1944
  super(config);
1945
1945
  _defineProperty(this, "_renderToolCalls", []);
1946
+ _defineProperty(this, "_hookRenderToolCalls", /* @__PURE__ */ new Map());
1947
+ _defineProperty(this, "_cachedMergedRenderToolCalls", null);
1946
1948
  _defineProperty(this, "_renderCustomMessages", []);
1947
1949
  _defineProperty(this, "_renderActivityMessages", []);
1948
1950
  _defineProperty(this, "_interruptElement", null);
@@ -1957,7 +1959,16 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1957
1959
  return this._renderActivityMessages;
1958
1960
  }
1959
1961
  get renderToolCalls() {
1960
- return this._renderToolCalls;
1962
+ if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
1963
+ if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
1964
+ const merged = /* @__PURE__ */ new Map();
1965
+ for (const rc of this._renderToolCalls) {
1966
+ var _rc$agentId;
1967
+ merged.set(`${(_rc$agentId = rc.agentId) !== null && _rc$agentId !== void 0 ? _rc$agentId : ""}:${rc.name}`, rc);
1968
+ }
1969
+ for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
1970
+ this._cachedMergedRenderToolCalls = Array.from(merged.values());
1971
+ return this._cachedMergedRenderToolCalls;
1961
1972
  }
1962
1973
  setRenderActivityMessages(renderers) {
1963
1974
  this._renderActivityMessages = renderers;
@@ -1967,6 +1978,24 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1967
1978
  }
1968
1979
  setRenderToolCalls(renderToolCalls) {
1969
1980
  this._renderToolCalls = renderToolCalls;
1981
+ this._cachedMergedRenderToolCalls = null;
1982
+ this._notifyRenderToolCallsChanged();
1983
+ }
1984
+ addHookRenderToolCall(entry) {
1985
+ var _entry$agentId;
1986
+ const key = `${(_entry$agentId = entry.agentId) !== null && _entry$agentId !== void 0 ? _entry$agentId : ""}:${entry.name}`;
1987
+ this._hookRenderToolCalls.set(key, entry);
1988
+ this._cachedMergedRenderToolCalls = null;
1989
+ this._notifyRenderToolCallsChanged();
1990
+ }
1991
+ removeHookRenderToolCall(name, agentId) {
1992
+ const key = `${agentId !== null && agentId !== void 0 ? agentId : ""}:${name}`;
1993
+ if (this._hookRenderToolCalls.delete(key)) {
1994
+ this._cachedMergedRenderToolCalls = null;
1995
+ this._notifyRenderToolCallsChanged();
1996
+ }
1997
+ }
1998
+ _notifyRenderToolCallsChanged() {
1970
1999
  this.notifySubscribers((subscriber) => {
1971
2000
  const reactSubscriber = subscriber;
1972
2001
  if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
@@ -2433,23 +2462,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2433
2462
  copilotkit.removeTool(name, tool.agentId);
2434
2463
  }
2435
2464
  copilotkit.addTool(tool);
2436
- if (tool.render) {
2437
- const keyOf = (rc) => {
2438
- var _rc$agentId;
2439
- return `${(_rc$agentId = rc.agentId) !== null && _rc$agentId !== void 0 ? _rc$agentId : ""}:${rc.name}`;
2440
- };
2441
- const currentRenderToolCalls = copilotkit.renderToolCalls;
2442
- const mergedMap = /* @__PURE__ */ new Map();
2443
- for (const rc of currentRenderToolCalls) mergedMap.set(keyOf(rc), rc);
2444
- const newEntry = {
2445
- name,
2446
- args: tool.parameters,
2447
- agentId: tool.agentId,
2448
- render: tool.render
2449
- };
2450
- mergedMap.set(keyOf(newEntry), newEntry);
2451
- copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
2452
- }
2465
+ if (tool.render && tool.parameters) copilotkit.addHookRenderToolCall({
2466
+ name,
2467
+ args: tool.parameters,
2468
+ agentId: tool.agentId,
2469
+ render: tool.render
2470
+ });
2453
2471
  return () => {
2454
2472
  copilotkit.removeTool(name, tool.agentId);
2455
2473
  };
@@ -2605,15 +2623,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2605
2623
  }),
2606
2624
  ...config.agentId ? { agentId: config.agentId } : {}
2607
2625
  });
2608
- const keyOf = (rc) => {
2609
- var _rc$agentId;
2610
- return `${(_rc$agentId = rc.agentId) !== null && _rc$agentId !== void 0 ? _rc$agentId : ""}:${rc.name}`;
2611
- };
2612
- const currentRenderToolCalls = copilotkit.renderToolCalls;
2613
- const mergedMap = /* @__PURE__ */ new Map();
2614
- for (const rc of currentRenderToolCalls) mergedMap.set(keyOf(rc), rc);
2615
- mergedMap.set(keyOf(renderer), renderer);
2616
- copilotkit.setRenderToolCalls(Array.from(mergedMap.values()));
2626
+ copilotkit.addHookRenderToolCall(renderer);
2617
2627
  }, [
2618
2628
  config.name,
2619
2629
  copilotkit,
@@ -2870,15 +2880,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2870
2880
  }, deps);
2871
2881
  (0, react.useEffect)(() => {
2872
2882
  return () => {
2873
- const keyOf = (rc) => {
2874
- var _rc$agentId;
2875
- return `${(_rc$agentId = rc.agentId) !== null && _rc$agentId !== void 0 ? _rc$agentId : ""}:${rc.name}`;
2876
- };
2877
- const filtered = copilotkit.renderToolCalls.filter((rc) => keyOf(rc) !== keyOf({
2878
- name: tool.name,
2879
- agentId: tool.agentId
2880
- }));
2881
- copilotkit.setRenderToolCalls(filtered);
2883
+ copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);
2882
2884
  };
2883
2885
  }, [
2884
2886
  copilotkit,