@aigentyc/chat-sdk 0.5.5 → 0.7.0

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.
Files changed (52) hide show
  1. package/context7.json +1 -1
  2. package/dist/{ChatInterface-Bo0dU48x.d.cts → ChatInterface-CJwumV6Z.d.cts} +1 -1
  3. package/dist/{ChatInterface-D5tY6WT1.d.ts → ChatInterface-jIlVCXyV.d.ts} +1 -1
  4. package/dist/{SlotsContext-hUp2jze9.d.ts → SlotsContext-BFyBOPC2.d.ts} +1 -1
  5. package/dist/{SlotsContext-p_bTEjGT.d.cts → SlotsContext-CvGHgMRZ.d.cts} +1 -1
  6. package/dist/ai-elements.cjs +2 -2
  7. package/dist/ai-elements.cjs.map +1 -1
  8. package/dist/ai-elements.js +2 -2
  9. package/dist/ai-elements.js.map +1 -1
  10. package/dist/{chunk-G63CLUHC.js → chunk-2HJZDMY2.js} +134 -9
  11. package/dist/chunk-2HJZDMY2.js.map +1 -0
  12. package/dist/{chunk-ZPOCKCBF.js → chunk-4DC55YI3.js} +3 -3
  13. package/dist/{chunk-ZPOCKCBF.js.map → chunk-4DC55YI3.js.map} +1 -1
  14. package/dist/{chunk-7TMQBROA.js → chunk-7N5ELRVH.js} +4 -4
  15. package/dist/{chunk-7TMQBROA.js.map → chunk-7N5ELRVH.js.map} +1 -1
  16. package/dist/{chunk-AQTN4QLR.cjs → chunk-MN7RYGXK.cjs} +6 -6
  17. package/dist/{chunk-AQTN4QLR.cjs.map → chunk-MN7RYGXK.cjs.map} +1 -1
  18. package/dist/{chunk-7MHR4BSJ.cjs → chunk-SOU2OES4.cjs} +21 -21
  19. package/dist/{chunk-7MHR4BSJ.cjs.map → chunk-SOU2OES4.cjs.map} +1 -1
  20. package/dist/{chunk-JJRLHXHZ.cjs → chunk-XV7N7UXF.cjs} +133 -8
  21. package/dist/chunk-XV7N7UXF.cjs.map +1 -0
  22. package/dist/components.cjs +15 -15
  23. package/dist/components.d.cts +3 -3
  24. package/dist/components.d.ts +3 -3
  25. package/dist/components.js +4 -4
  26. package/dist/core.d.cts +2 -2
  27. package/dist/core.d.ts +2 -2
  28. package/dist/hooks.cjs +4 -4
  29. package/dist/hooks.d.cts +2 -2
  30. package/dist/hooks.d.ts +2 -2
  31. package/dist/hooks.js +1 -1
  32. package/dist/i18n.d.cts +1 -1
  33. package/dist/i18n.d.ts +1 -1
  34. package/dist/index.cjs +25 -23
  35. package/dist/index.cjs.map +1 -1
  36. package/dist/index.d.cts +5 -5
  37. package/dist/index.d.ts +5 -5
  38. package/dist/index.js +8 -6
  39. package/dist/index.js.map +1 -1
  40. package/dist/llms-full.txt +9 -9
  41. package/dist/styles.css +1 -1
  42. package/dist/theme.d.cts +1 -1
  43. package/dist/theme.d.ts +1 -1
  44. package/dist/tools.cjs +5 -5
  45. package/dist/tools.d.cts +2 -2
  46. package/dist/tools.d.ts +2 -2
  47. package/dist/tools.js +2 -2
  48. package/dist/{types-DRa1zFlN.d.ts → types-BxvFxOg1.d.cts} +9 -0
  49. package/dist/{types-DRa1zFlN.d.cts → types-BxvFxOg1.d.ts} +9 -0
  50. package/package.json +5 -5
  51. package/dist/chunk-G63CLUHC.js.map +0 -1
  52. package/dist/chunk-JJRLHXHZ.cjs.map +0 -1
@@ -3,7 +3,7 @@ import { loadMessages, saveMessages, clearMessages } from './chunk-CNPYBLLT.js';
3
3
  import { createContext, useContext, useState, useRef, useMemo, useEffect, useCallback } from 'react';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
  import { useChat } from '@ai-sdk/react';
6
- import { DefaultChatTransport } from 'ai';
6
+ import { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls } from 'ai';
7
7
 
8
8
  var SlotsContext = createContext({});
9
9
  function SlotsProvider({ slots = {}, children }) {
@@ -25,7 +25,82 @@ function renderSlot(name, props, DefaultComponent, slots) {
25
25
  const Default = DefaultComponent;
26
26
  return /* @__PURE__ */ jsx(Default, { ...spreadProps });
27
27
  }
28
+
29
+ // src/core/browser-fetch.ts
30
+ var FETCH_TIMEOUT_MS = 15e3;
31
+ function failure(toolName, detail) {
32
+ return {
33
+ kind: "error",
34
+ errorText: `${toolName} could NOT run (${detail}). This is a failed check, NOT an empty result \u2014 do not say the item is missing or not in the catalogue. Tell the user the lookup could not be completed right now and offer to try again or to open a request.`
35
+ };
36
+ }
37
+ async function runBrowserFetchTool(call) {
38
+ const endpoint = `${call.apiEndpoint || ""}/api/kb/tools/browser-fetch`;
39
+ const post = (payload) => fetch(endpoint, {
40
+ method: "POST",
41
+ headers: {
42
+ "Content-Type": "application/json",
43
+ ...call.apiKey ? { Authorization: `Bearer ${call.apiKey}` } : {}
44
+ },
45
+ body: JSON.stringify({
46
+ projectId: call.projectId,
47
+ sessionId: call.sessionId,
48
+ toolName: call.toolName,
49
+ input: call.input ?? {},
50
+ ...payload
51
+ })
52
+ });
53
+ try {
54
+ const resolved = await post({ phase: "resolve" });
55
+ if (resolved.status === 404) return { kind: "not-browser-fetch" };
56
+ if (!resolved.ok) {
57
+ return failure(call.toolName, `prepare step HTTP ${resolved.status}`);
58
+ }
59
+ const { request } = await resolved.json();
60
+ const startedAt = Date.now();
61
+ let response;
62
+ try {
63
+ const res = await fetch(request.url, {
64
+ method: request.method,
65
+ headers: request.headers,
66
+ body: request.body,
67
+ credentials: "include",
68
+ signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
69
+ });
70
+ if (!res.ok) {
71
+ return failure(call.toolName, `HTTP ${res.status}`);
72
+ }
73
+ response = await res.json();
74
+ } catch (err) {
75
+ return failure(call.toolName, err instanceof Error ? err.message : String(err));
76
+ }
77
+ const completed = await post({
78
+ phase: "complete",
79
+ response,
80
+ latencyMs: Date.now() - startedAt
81
+ });
82
+ if (!completed.ok) {
83
+ const detail = await completed.json().catch(() => null);
84
+ return failure(call.toolName, detail?.error || `HTTP ${completed.status}`);
85
+ }
86
+ const { output } = await completed.json();
87
+ return { kind: "output", output };
88
+ } catch (err) {
89
+ return failure(call.toolName, err instanceof Error ? err.message : String(err));
90
+ }
91
+ }
92
+ function pendingToolCalls(message) {
93
+ const out = [];
94
+ for (const raw of message.parts ?? []) {
95
+ const p = raw;
96
+ if (p.state !== "input-available" || !p.toolCallId) continue;
97
+ const toolName = p.type === "dynamic-tool" ? p.toolName : p.type.startsWith("tool-") ? p.type.slice(5) : void 0;
98
+ if (toolName) out.push({ toolName, toolCallId: p.toolCallId, input: p.input });
99
+ }
100
+ return out;
101
+ }
28
102
  var SESSION_KEY_PREFIX = "aigentyc-session-";
103
+ var MAX_BROWSER_TOOL_CALLS_PER_TURN = 6;
29
104
  var LEGACY_MESSAGE_KEY_PREFIX = "aigentyc-messages-";
30
105
  function dropLegacyMessageStore(projectId) {
31
106
  if (typeof window === "undefined") return;
@@ -76,12 +151,14 @@ function ChatContextProvider({
76
151
  const pageRef = useRef({
77
152
  pageUrl: config.pageUrl,
78
153
  pageTitle: config.pageTitle,
79
- pageContext: config.pageContext
154
+ pageContext: config.pageContext,
155
+ browserFetch: config.browserFetch === true
80
156
  });
81
157
  pageRef.current = {
82
158
  pageUrl: config.pageUrl,
83
159
  pageTitle: config.pageTitle,
84
- pageContext: config.pageContext
160
+ pageContext: config.pageContext,
161
+ browserFetch: config.browserFetch === true
85
162
  };
86
163
  const transport = useMemo(
87
164
  () => new DefaultChatTransport({
@@ -89,18 +166,49 @@ function ChatContextProvider({
89
166
  headers: config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : void 0,
90
167
  // A function body is resolved per request by the AI SDK transport.
91
168
  body: () => {
92
- const { pageUrl, pageTitle, pageContext } = pageRef.current;
169
+ const { pageUrl, pageTitle, pageContext, browserFetch } = pageRef.current;
93
170
  return {
94
171
  projectId: config.projectId,
95
172
  sessionId,
96
173
  ...pageUrl ? { pageUrl } : {},
97
174
  ...pageTitle ? { pageTitle } : {},
98
- ...pageContext !== void 0 ? { pageContext } : {}
175
+ ...pageContext !== void 0 ? { pageContext } : {},
176
+ ...browserFetch ? { clientCapabilities: ["browser_fetch"] } : {}
99
177
  };
100
178
  }
101
179
  }),
102
180
  [config.apiEndpoint, config.apiKey, config.projectId, sessionId]
103
181
  );
182
+ const browserAnsweredRef = useRef(/* @__PURE__ */ new Set());
183
+ const browserRunRef = useRef(/* @__PURE__ */ new Set());
184
+ const addToolOutputRef = useRef(null);
185
+ const runPendingBrowserTools = useCallback(
186
+ async (message) => {
187
+ if (!pageRef.current.browserFetch) return;
188
+ for (const call of pendingToolCalls(message)) {
189
+ const result = await runBrowserFetchTool({
190
+ apiEndpoint: config.apiEndpoint,
191
+ apiKey: config.apiKey,
192
+ projectId: config.projectId,
193
+ sessionId,
194
+ toolName: call.toolName,
195
+ input: call.input
196
+ });
197
+ if (result.kind === "not-browser-fetch") continue;
198
+ browserAnsweredRef.current.add(call.toolCallId);
199
+ browserRunRef.current.add(call.toolCallId);
200
+ addToolOutputRef.current?.(
201
+ result.kind === "output" ? { tool: call.toolName, toolCallId: call.toolCallId, output: result.output } : {
202
+ tool: call.toolName,
203
+ toolCallId: call.toolCallId,
204
+ state: "output-error",
205
+ errorText: result.errorText
206
+ }
207
+ );
208
+ }
209
+ },
210
+ [config.apiEndpoint, config.apiKey, config.projectId, sessionId]
211
+ );
104
212
  const {
105
213
  messages,
106
214
  sendMessage: sdkSendMessage,
@@ -109,18 +217,35 @@ function ChatContextProvider({
109
217
  stop,
110
218
  setMessages,
111
219
  regenerate,
112
- clearError
220
+ clearError,
221
+ addToolOutput
113
222
  } = useChat({
114
223
  id: sessionId,
115
224
  messages: initialMessages,
116
225
  transport,
117
- onFinish: (message) => {
226
+ // Resume only a turn whose last open calls were answered by this widget —
227
+ // never one merely ending on a server tool, which would loop.
228
+ sendAutomaticallyWhen: ({ messages: all }) => {
229
+ if (!lastAssistantMessageIsCompleteWithToolCalls({ messages: all })) return false;
230
+ const last = all[all.length - 1];
231
+ const parts = last.parts ?? [];
232
+ const answered = parts.some(
233
+ (p) => p.toolCallId && browserAnsweredRef.current.delete(p.toolCallId)
234
+ );
235
+ const rounds = parts.filter(
236
+ (p) => p.toolCallId && browserRunRef.current.has(p.toolCallId)
237
+ ).length;
238
+ return answered && rounds <= MAX_BROWSER_TOOL_CALLS_PER_TURN;
239
+ },
240
+ onFinish: ({ message, isAbort, isError }) => {
241
+ if (!isAbort && !isError) void runPendingBrowserTools(message);
118
242
  callbacksRef.current?.onMessageReceived?.(message);
119
243
  },
120
244
  onError: (err) => {
121
245
  callbacksRef.current?.onError?.(err);
122
246
  }
123
247
  });
248
+ addToolOutputRef.current = addToolOutput;
124
249
  const status = error ? "error" : sdkStatus === "streaming" || sdkStatus === "submitted" ? "streaming" : "idle";
125
250
  useEffect(() => {
126
251
  persistMessages(projectId, sessionId, messages);
@@ -235,5 +360,5 @@ function useChatContext() {
235
360
  }
236
361
 
237
362
  export { ChatContext, ChatContextProvider, SlotsProvider, renderSlot, useChatContext, useSlot, useSlots };
238
- //# sourceMappingURL=chunk-G63CLUHC.js.map
239
- //# sourceMappingURL=chunk-G63CLUHC.js.map
363
+ //# sourceMappingURL=chunk-2HJZDMY2.js.map
364
+ //# sourceMappingURL=chunk-2HJZDMY2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/providers/SlotsContext.tsx","../src/core/browser-fetch.ts","../src/providers/ChatContext.tsx"],"names":["createContext","clearMessages","jsx","useContext"],"mappings":"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","file":"chunk-2HJZDMY2.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport {\n createContext,\n useContext,\n type ReactNode,\n type ComponentType,\n} from \"react\";\n\n/**\n * All available slot names that can be overridden.\n */\nexport type SlotName =\n | \"header\"\n | \"footer\"\n | \"input\"\n | \"welcomePage\"\n | \"userMessage\"\n | \"assistantMessage\"\n | \"systemMessage\"\n | \"loader\"\n | \"feedback\"\n | \"tools\"\n | \"toolRenderers\"\n | \"liveChatPanel\"\n | \"satisfactionRating\"\n | \"visitorIdentityForm\"\n | \"floatingButton\"\n | \"emptyState\"\n | \"error\";\n\n/**\n * A slot component receives the default component as a prop alongside its own props.\n */\nexport type SlotComponent<P = Record<string, unknown>> = ComponentType<\n P & { DefaultComponent: ComponentType<P> }\n>;\n\n/**\n * Map of slot name to override component.\n */\nexport type SlotMap = Partial<Record<SlotName, SlotComponent<any>>>;\n\nconst SlotsContext = createContext<SlotMap>({});\n\n/** Props for the SlotsProvider component. */\nexport interface SlotsProviderProps {\n /** Slot overrides map */\n slots?: SlotMap;\n children: ReactNode;\n}\n\n/**\n * Provides slot overrides to descendant components.\n * Wrap your chat tree with this provider and pass a `slots` map\n * to replace built-in UI sections.\n */\nexport function SlotsProvider({ slots = {}, children }: SlotsProviderProps) {\n return (\n <SlotsContext.Provider value={slots}>{children}</SlotsContext.Provider>\n );\n}\n\n/**\n * Returns the full SlotMap from context.\n */\nexport function useSlots(): SlotMap {\n return useContext(SlotsContext);\n}\n\n/**\n * Returns the override component for the given slot name, or undefined if none is set.\n */\nexport function useSlot<P = Record<string, unknown>>(\n name: SlotName\n): SlotComponent<P> | undefined {\n const slots = useContext(SlotsContext);\n return slots[name] as SlotComponent<P> | undefined;\n}\n\n/**\n * Renders a slot: if an override exists, renders it with `{...props, DefaultComponent}`.\n * Otherwise renders the DefaultComponent with the given props.\n *\n * The generic `P` is NOT constrained to `Record<string, unknown>` so concrete\n * component prop types (e.g. `ChatHeaderProps`) flow through at call sites\n * without `as never` casts. Internal spreads are cast through\n * `Record<string, unknown>` — safe because JSX spread accepts any record.\n *\n * @param name - The slot name\n * @param props - Props to pass to the component\n * @param DefaultComponent - The built-in fallback component\n */\nexport function renderSlot<P>(\n name: SlotName,\n props: P,\n DefaultComponent: ComponentType<P>,\n slots: SlotMap\n): React.ReactElement {\n const spreadProps = props as unknown as Record<string, unknown>;\n const Override = slots[name] as\n | ComponentType<Record<string, unknown> & { DefaultComponent: ComponentType<P> }>\n | undefined;\n if (Override) {\n return <Override {...spreadProps} DefaultComponent={DefaultComponent} />;\n }\n const Default = DefaultComponent as ComponentType<Record<string, unknown>>;\n return <Default {...spreadProps} />;\n}\n","/**\n * Browser-fetch tools — tools whose HTTP call must run in the visitor's browser\n * (apiConfig.fetchFrom = \"browser\" on the platform), typically because the API\n * answers per visitor session: a signed-in customer's private catalogue is\n * invisible to any server-side call, which has no access to their cookies.\n *\n * When the chat is configured with `browserFetch`, the backend registers those\n * tools without a server `execute`, so the turn pauses on the call. This module\n * runs one such call:\n * 1. asks the platform for the request to make (`phase: \"resolve\"`);\n * 2. makes it here, with `credentials: \"include\"`;\n * 3. hands the raw response back for the tool's own transform (`phase:\n * \"complete\"`), which also records it in analytics;\n * and returns the tool output the chat resumes with.\n */\n\nexport interface BrowserFetchCall {\n apiEndpoint: string;\n apiKey?: string;\n projectId: string;\n sessionId: string;\n toolName: string;\n input: unknown;\n}\n\nexport type BrowserFetchResult =\n | { kind: \"output\"; output: unknown }\n | { kind: \"error\"; errorText: string }\n /** The platform says this is not a browser-fetch tool — leave the call alone. */\n | { kind: \"not-browser-fetch\" };\n\n/** Upper bound for the visitor-side request, so a dead API cannot hang the turn. */\nconst FETCH_TIMEOUT_MS = 15_000;\n\n/**\n * What the model reads when a browser-run call fails. It must not be mistaken\n * for an empty result: a lookup that never ran is not \"not found\", and saying\n * so to a signed-in customer about their own product is the worst outcome.\n */\nfunction failure(toolName: string, detail: string): BrowserFetchResult {\n return {\n kind: \"error\",\n errorText:\n `${toolName} could NOT run (${detail}). This is a failed check, NOT an empty result — ` +\n `do not say the item is missing or not in the catalogue. Tell the user the lookup ` +\n `could not be completed right now and offer to try again or to open a request.`,\n };\n}\n\nexport async function runBrowserFetchTool(\n call: BrowserFetchCall,\n): Promise<BrowserFetchResult> {\n const endpoint = `${call.apiEndpoint || \"\"}/api/kb/tools/browser-fetch`;\n const post = (payload: Record<string, unknown>) =>\n fetch(endpoint, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(call.apiKey ? { Authorization: `Bearer ${call.apiKey}` } : {}),\n },\n body: JSON.stringify({\n projectId: call.projectId,\n sessionId: call.sessionId,\n toolName: call.toolName,\n input: call.input ?? {},\n ...payload,\n }),\n });\n\n try {\n const resolved = await post({ phase: \"resolve\" });\n if (resolved.status === 404) return { kind: \"not-browser-fetch\" };\n if (!resolved.ok) {\n return failure(call.toolName, `prepare step HTTP ${resolved.status}`);\n }\n const { request } = (await resolved.json()) as {\n request: {\n url: string;\n method: \"GET\" | \"POST\";\n headers: Record<string, string>;\n body?: string;\n };\n };\n\n const startedAt = Date.now();\n let response: unknown;\n try {\n const res = await fetch(request.url, {\n method: request.method,\n headers: request.headers,\n body: request.body,\n credentials: \"include\",\n signal: AbortSignal.timeout(FETCH_TIMEOUT_MS),\n });\n if (!res.ok) {\n return failure(call.toolName, `HTTP ${res.status}`);\n }\n response = await res.json();\n } catch (err) {\n return failure(call.toolName, err instanceof Error ? err.message : String(err));\n }\n\n const completed = await post({\n phase: \"complete\",\n response,\n latencyMs: Date.now() - startedAt,\n });\n if (!completed.ok) {\n const detail = (await completed.json().catch(() => null)) as {\n error?: string;\n } | null;\n return failure(call.toolName, detail?.error || `HTTP ${completed.status}`);\n }\n const { output } = (await completed.json()) as { output: unknown };\n return { kind: \"output\", output };\n } catch (err) {\n return failure(call.toolName, err instanceof Error ? err.message : String(err));\n }\n}\n\ninterface PendingToolPart {\n type: string;\n toolName?: string;\n toolCallId?: string;\n state?: string;\n input?: unknown;\n}\n\n/**\n * Tool calls in a finished assistant message that are still waiting for an\n * output — the candidates for browser execution. The platform decides which\n * of them really are browser-fetch tools (others, e.g. an upload-driven image\n * analysis, answer `not-browser-fetch` and are left alone).\n */\nexport function pendingToolCalls(message: {\n parts?: unknown[];\n}): Array<{ toolName: string; toolCallId: string; input: unknown }> {\n const out: Array<{ toolName: string; toolCallId: string; input: unknown }> = [];\n for (const raw of message.parts ?? []) {\n const p = raw as PendingToolPart;\n if (p.state !== \"input-available\" || !p.toolCallId) continue;\n const toolName =\n p.type === \"dynamic-tool\"\n ? p.toolName\n : p.type.startsWith(\"tool-\")\n ? p.type.slice(5)\n : undefined;\n if (toolName) out.push({ toolName, toolCallId: p.toolCallId, input: p.input });\n }\n return out;\n}\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useState,\n useCallback,\n useRef,\n useEffect,\n useMemo,\n type ReactNode,\n} from \"react\";\nimport type {\n ChatConfig,\n ChatMessage,\n ChatEventCallbacks,\n ChatAttachmentInput,\n} from \"../core/types\";\nimport { useChat } from \"@ai-sdk/react\";\nimport { DefaultChatTransport, lastAssistantMessageIsCompleteWithToolCalls } from \"ai\";\nimport { pendingToolCalls, runBrowserFetchTool } from \"../core/browser-fetch\";\nimport {\n clearMessages as clearStoredMessages,\n loadMessages as loadStoredMessages,\n saveMessages as saveStoredMessages,\n type StoredMessage,\n} from \"../core/message-store\";\n\ntype ChatStatus = \"idle\" | \"streaming\" | \"error\";\n\ninterface ActiveTool {\n toolName: string;\n state: \"partial-call\" | \"call\" | \"output-available\";\n args: Record<string, unknown>;\n result?: unknown;\n renderMode: string;\n}\n\nconst SESSION_KEY_PREFIX = \"aigentyc-session-\";\n\n/** Browser-run tool calls one assistant turn may resume after (see browser-fetch). */\nconst MAX_BROWSER_TOOL_CALLS_PER_TURN = 6;\n\n/**\n * Where this provider used to keep history, before it moved to\n * `core/message-store`.\n *\n * Worth deleting rather than leaving behind. The old writer had no size cap and\n * no expiry, so an established visitor can be carrying a large dead blob under\n * this key — and `localStorage` is a ~5 MB budget shared by the whole origin.\n * Nothing reads the key any more, but the space it holds is space the new\n * store's writes need, and those writes fail SILENTLY when the quota is gone.\n * An orphan left in place would mean persistence quietly stopping for exactly\n * the visitors who had used the chat the most.\n */\nconst LEGACY_MESSAGE_KEY_PREFIX = \"aigentyc-messages-\";\n\nfunction dropLegacyMessageStore(projectId: string): void {\n if (typeof window === \"undefined\") return;\n try {\n localStorage.removeItem(LEGACY_MESSAGE_KEY_PREFIX + projectId);\n } catch {\n // Unavailable or blocked — the old key is harmless, just wasteful.\n }\n}\n\nfunction getOrCreateSessionId(projectId: string): string {\n if (typeof window === \"undefined\") return crypto.randomUUID();\n const key = SESSION_KEY_PREFIX + projectId;\n try {\n const stored = sessionStorage.getItem(key);\n if (stored) return stored;\n const id = crypto.randomUUID();\n sessionStorage.setItem(key, id);\n return id;\n } catch {\n return crypto.randomUUID();\n }\n}\n\n/**\n * History is stored per project AND per session, by `core/message-store`.\n *\n * This used to be three local helpers keyed on `projectId` alone, with no\n * expiry and no size bound, while `message-store` — written for exactly this\n * job, and exported from the package — went unused. The difference is not\n * cosmetic:\n *\n * - **A session could not escape a poisoned history.** The server refuses a\n * turn whose replayed history is too long or too large. Because every\n * session in the project read the same key, that history came back on the\n * next page load, in the next tab and in a new session — so a conversation\n * that broke once answered nothing ever again, which is exactly how this was\n * reported from the field.\n * - **Sessions leaked into each other.** A second tab adopted the first tab's\n * conversation while reporting a different `sessionId` upstream, so the\n * transcript the server logged did not match the one on screen.\n * - **Nothing ever expired.** `message-store` drops history after 24 hours and\n * trims it when it outgrows 200 KB.\n *\n * Persistence across navigation is unchanged: the session id lives in\n * `sessionStorage`, which survives a full page load in the same tab.\n */\nfunction persistMessages(\n projectId: string,\n sessionId: string,\n messages: unknown[]\n): void {\n saveStoredMessages(projectId, sessionId, messages as StoredMessage[]);\n}\n\nfunction loadPersistedMessages(\n projectId: string,\n sessionId: string\n): ChatMessage[] {\n return loadStoredMessages(projectId, sessionId) as unknown as ChatMessage[];\n}\n\nfunction clearPersistedMessages(projectId: string, sessionId: string): void {\n clearStoredMessages(projectId, sessionId);\n}\n\nexport interface ChatContextValue {\n messages: ChatMessage[];\n status: ChatStatus;\n error: Error | undefined;\n sessionId: string;\n config: ChatConfig;\n activeTools: ActiveTool[];\n /**\n * Sends a user turn. `files` travel with it as message parts; a turn carrying\n * files may have empty text — an image on its own is a question.\n */\n sendMessage: (content: string, files?: ChatAttachmentInput[]) => void;\n stopGeneration: () => void;\n /**\n * Re-run the last turn after a failure. No-op while a turn is in flight.\n *\n * Worth offering for a transient refusal — a rate limit, a dropped stream, a\n * momentary 503. It cannot clear a refusal caused by the history itself,\n * because the same history is what gets re-sent; that needs\n * {@link ChatContextValue.newConversation}.\n */\n retryLastTurn: () => void;\n /**\n * Replace a sent user message with new text and answer it again.\n *\n * Everything after that message is dropped, as in ChatGPT's edit: the\n * conversation continues from the corrected question, not alongside the old\n * one. A turn still streaming is stopped first.\n */\n editMessage: (messageId: string, content: string) => void;\n newConversation: () => void;\n clearMessages: () => void;\n callbacks?: ChatEventCallbacks;\n}\n\nexport const ChatContext = createContext<ChatContextValue | null>(null);\n\nexport interface ChatContextProviderProps {\n config: ChatConfig;\n callbacks?: ChatEventCallbacks;\n children: ReactNode;\n}\n\n/**\n * Internal provider that manages chat state via @ai-sdk/react `useChat`.\n * Handles message persistence and session management.\n */\nexport function ChatContextProvider({\n config,\n callbacks,\n children,\n}: ChatContextProviderProps) {\n const projectId = config.projectId || \"default\";\n const [sessionId, setSessionId] = useState(() => getOrCreateSessionId(projectId));\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n // Re-load persisted messages whenever the session changes (incl. after\n // newConversation()). Keying only on mount cached the original array, so\n // useChat would re-inject the OLD messages into the new sessionId — a real\n // \"new chat\" effectively kept the old conversation alive.\n const initialMessages = useMemo(\n () => loadPersistedMessages(projectId, sessionId),\n [projectId, sessionId]\n );\n\n useEffect(() => {\n dropLegacyMessageStore(projectId);\n }, [projectId]);\n\n // Page context is whatever the host page looks like *right now*, so it is read\n // through a ref at send time rather than captured when the transport is built.\n // Rebuilding the transport on every navigation would remount `useChat` and\n // drop an in-flight stream — in a single-page host that is one route change.\n const pageRef = useRef({\n pageUrl: config.pageUrl,\n pageTitle: config.pageTitle,\n pageContext: config.pageContext,\n browserFetch: config.browserFetch === true,\n });\n pageRef.current = {\n pageUrl: config.pageUrl,\n pageTitle: config.pageTitle,\n pageContext: config.pageContext,\n browserFetch: config.browserFetch === true,\n };\n\n const transport = useMemo(\n () =>\n new DefaultChatTransport({\n api: `${config.apiEndpoint || \"\"}/api/kb/chat`,\n headers: config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : undefined,\n // A function body is resolved per request by the AI SDK transport.\n body: () => {\n const { pageUrl, pageTitle, pageContext, browserFetch } = pageRef.current;\n return {\n projectId: config.projectId,\n sessionId,\n ...(pageUrl ? { pageUrl } : {}),\n ...(pageTitle ? { pageTitle } : {}),\n ...(pageContext !== undefined ? { pageContext } : {}),\n ...(browserFetch ? { clientCapabilities: [\"browser_fetch\"] } : {}),\n };\n },\n }),\n [config.apiEndpoint, config.apiKey, config.projectId, sessionId]\n );\n\n // Browser-fetch tools (see core/browser-fetch): a turn that ends on such a\n // call is paused until this widget runs it and hands the output back. Ids of\n // the calls answered here — only those resume the turn automatically.\n const browserAnsweredRef = useRef(new Set<string>());\n // Every call ever answered here, so a turn's browser rounds can be counted.\n const browserRunRef = useRef(new Set<string>());\n const addToolOutputRef = useRef<((args: never) => unknown) | null>(null);\n const runPendingBrowserTools = useCallback(\n async (message: { parts?: unknown[] }) => {\n if (!pageRef.current.browserFetch) return;\n for (const call of pendingToolCalls(message)) {\n const result = await runBrowserFetchTool({\n apiEndpoint: config.apiEndpoint,\n apiKey: config.apiKey,\n projectId: config.projectId,\n sessionId,\n toolName: call.toolName,\n input: call.input,\n });\n if (result.kind === \"not-browser-fetch\") continue;\n browserAnsweredRef.current.add(call.toolCallId);\n browserRunRef.current.add(call.toolCallId);\n addToolOutputRef.current?.(\n (result.kind === \"output\"\n ? { tool: call.toolName, toolCallId: call.toolCallId, output: result.output }\n : {\n tool: call.toolName,\n toolCallId: call.toolCallId,\n state: \"output-error\",\n errorText: result.errorText,\n }) as never\n );\n }\n },\n [config.apiEndpoint, config.apiKey, config.projectId, sessionId]\n );\n\n const {\n messages,\n sendMessage: sdkSendMessage,\n status: sdkStatus,\n error,\n stop,\n setMessages,\n regenerate,\n clearError,\n addToolOutput,\n } = useChat({\n id: sessionId,\n messages: initialMessages as never,\n transport,\n // Resume only a turn whose last open calls were answered by this widget —\n // never one merely ending on a server tool, which would loop.\n sendAutomaticallyWhen: ({ messages: all }) => {\n if (!lastAssistantMessageIsCompleteWithToolCalls({ messages: all })) return false;\n const last = all[all.length - 1] as { parts?: Array<{ toolCallId?: string }> };\n const parts = last.parts ?? [];\n const answered = parts.some(\n (p) => p.toolCallId && browserAnsweredRef.current.delete(p.toolCallId)\n );\n // A continuation keeps the same assistant message, so its browser-run\n // calls are this turn's rounds. Cap them: a model that keeps re-calling a\n // failing tool would otherwise resume forever, one request per error.\n const rounds = parts.filter(\n (p) => p.toolCallId && browserRunRef.current.has(p.toolCallId)\n ).length;\n return answered && rounds <= MAX_BROWSER_TOOL_CALLS_PER_TURN;\n },\n onFinish: ({ message, isAbort, isError }) => {\n if (!isAbort && !isError) void runPendingBrowserTools(message);\n callbacksRef.current?.onMessageReceived?.(message as unknown as ChatMessage);\n },\n onError: (err) => {\n callbacksRef.current?.onError?.(err);\n },\n });\n\n addToolOutputRef.current = addToolOutput as unknown as (args: never) => unknown;\n\n const status: ChatStatus = error\n ? \"error\"\n : sdkStatus === \"streaming\" || sdkStatus === \"submitted\"\n ? \"streaming\"\n : \"idle\";\n\n useEffect(() => {\n persistMessages(projectId, sessionId, messages);\n }, [messages, projectId, sessionId]);\n\n const activeTools = useMemo<ActiveTool[]>(() => {\n if (messages.length === 0) return [];\n const last = messages[messages.length - 1] as { role: string; parts?: unknown[] };\n if (last.role !== \"assistant\" || !Array.isArray(last.parts)) return [];\n return (last.parts as Array<Record<string, unknown>>)\n .filter((p) => typeof p.type === \"string\" && (p.type as string).startsWith(\"tool-\"))\n .map((p) => ({\n toolName: (p.toolName as string) || (p.type as string).replace(\"tool-\", \"\"),\n state: (p.state as ActiveTool[\"state\"]) || \"output-available\",\n args: (p.args as Record<string, unknown>) || {},\n result: p.result,\n renderMode: (p.renderMode as string) || \"inline\",\n }));\n }, [messages]);\n\n const sendMessage = useCallback(\n (content: string, files?: ChatAttachmentInput[]) => {\n // An attachment is a message on its own, so an empty string only blocks\n // the send when nothing else is going with it.\n if (!content.trim() && (!files || files.length === 0)) return;\n callbacksRef.current?.onMessageSent?.({\n id: crypto.randomUUID(),\n role: \"user\",\n content,\n } as ChatMessage);\n sdkSendMessage({\n text: content,\n ...(files && files.length > 0\n ? { files: files.map((f) => ({ ...f, type: \"file\" as const })) }\n : {}),\n });\n },\n [sdkSendMessage]\n );\n\n const stopGeneration = useCallback(() => stop(), [stop]);\n\n // `clearError` first: the error is what the UI is rendering, and leaving it\n // set would keep the failure card on screen next to the turn now streaming.\n //\n // The empty check is not defensive padding. `regenerate()` THROWS when there\n // is no message to re-run, and a host that calls `clearMessages()` while a\n // failure is on screen leaves exactly that state — no messages, error still\n // set, so the card is still rendered and still offering its button. Left\n // alone it would also be an unhandled rejection, since nothing awaits this.\n const retryLastTurn = useCallback(() => {\n clearError();\n if (messages.length === 0) return;\n regenerate().catch(() => {\n // Request failures already land in `error` via useChat's own handling;\n // this only stops a rejected promise escaping the click handler.\n });\n }, [clearError, regenerate, messages]);\n\n const editMessage = useCallback(\n (messageId: string, content: string) => {\n if (!content.trim()) return;\n const target = messages.find((m) => m.id === messageId);\n // useChat throws for an unknown id or a non-user message; refuse quietly\n // instead, since this is wired straight to a click.\n if (!target || target.role !== \"user\") return;\n clearError();\n if (sdkStatus === \"streaming\" || sdkStatus === \"submitted\") stop();\n callbacksRef.current?.onMessageSent?.({\n id: messageId,\n role: \"user\",\n content,\n } as ChatMessage);\n sdkSendMessage({ text: content, messageId }).catch(() => {\n // Request failures land in `error` via useChat's own handling.\n });\n },\n [clearError, messages, sdkSendMessage, sdkStatus, stop]\n );\n\n const newConversation = useCallback(() => {\n setMessages([]);\n clearPersistedMessages(projectId, sessionId);\n if (typeof window !== \"undefined\") {\n try {\n sessionStorage.removeItem(SESSION_KEY_PREFIX + projectId);\n } catch {\n // ignore\n }\n }\n setSessionId(getOrCreateSessionId(projectId));\n }, [projectId, sessionId, setMessages]);\n\n const clearMessages = useCallback(() => {\n setMessages([]);\n clearPersistedMessages(projectId, sessionId);\n }, [projectId, sessionId, setMessages]);\n\n const value = useMemo<ChatContextValue>(\n () => ({\n messages: messages as unknown as ChatMessage[],\n status,\n error: error as Error | undefined,\n sessionId,\n config,\n activeTools,\n sendMessage,\n stopGeneration,\n retryLastTurn,\n editMessage,\n newConversation,\n clearMessages,\n callbacks: callbacksRef.current,\n }),\n [\n messages,\n status,\n error,\n sessionId,\n config,\n activeTools,\n sendMessage,\n stopGeneration,\n retryLastTurn,\n editMessage,\n newConversation,\n clearMessages,\n ]\n );\n\n return <ChatContext.Provider value={value}>{children}</ChatContext.Provider>;\n}\n\n/**\n * Returns the chat context. Must be used within a `ChatContextProvider`.\n */\nexport function useChatContext(): ChatContextValue {\n const ctx = useContext(ChatContext);\n if (!ctx) {\n throw new Error(\n \"useChatContext must be used within a ChatProvider or ChatContextProvider\"\n );\n }\n return ctx;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { useSlots, ChatContext } from './chunk-G63CLUHC.js';
2
+ import { useSlots, ChatContext } from './chunk-2HJZDMY2.js';
3
3
  import { processImagesInHtml } from './chunk-PS3U7T37.js';
4
4
  import { Spinner } from './chunk-4QT25AXI.js';
5
5
  import { Card } from './chunk-NPJKLYLV.js';
@@ -579,5 +579,5 @@ function pickDefaultForMode(mode) {
579
579
  }
580
580
 
581
581
  export { ComponentRenderer, SearchKnowledgeBaseRenderer, ToolRenderer };
582
- //# sourceMappingURL=chunk-ZPOCKCBF.js.map
583
- //# sourceMappingURL=chunk-ZPOCKCBF.js.map
582
+ //# sourceMappingURL=chunk-4DC55YI3.js.map
583
+ //# sourceMappingURL=chunk-4DC55YI3.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tools/SearchKnowledgeBaseRenderer.tsx","../src/tools/ComponentRenderer.tsx","../src/tools/useSafeChatCallbacks.ts","../src/tools/tool-registry.ts","../src/tools/ToolRenderer.tsx"],"names":["useState","jsxs","jsx","useEffect"],"mappings":"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","file":"chunk-ZPOCKCBF.js","sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Card } from \"../ui/card\";\nimport type { ToolRendererProps } from \"../core/types\";\n\ninterface KbSource {\n rank?: number;\n id?: number | string;\n content?: string;\n documentName?: string;\n sourceUrl?: string | null;\n similarity?: number;\n pageTitle?: string | null;\n summary?: string | null;\n relevance?: string;\n}\n\ninterface KbResult {\n found?: boolean;\n totalResults?: number;\n generatedQueries?: string[];\n sources?: KbSource[];\n}\n\nfunction truncate(text: string, max = 220) {\n if (text.length <= max) return text;\n return text.slice(0, max).trimEnd() + \"…\";\n}\n\nexport function SearchKnowledgeBaseRenderer(props: ToolRendererProps) {\n const data = (props.result?._displayData ?? props.result?.data) as KbResult | undefined;\n const [expanded, setExpanded] = useState(false);\n\n if (!data || !data.found || !Array.isArray(data.sources) || data.sources.length === 0) {\n return null;\n }\n\n const sources = data.sources;\n const visible = expanded ? sources : sources.slice(0, 3);\n\n return (\n <Card className=\"p-3 text-sm\">\n <div className=\"mb-2 flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n Found <strong className=\"text-foreground\">{data.totalResults ?? sources.length}</strong>{\" \"}\n source{(data.totalResults ?? sources.length) === 1 ? \"\" : \"s\"}\n {data.generatedQueries?.length\n ? ` for \"${data.generatedQueries.join(\", \")}\"`\n : \"\"}\n </span>\n </div>\n\n <ul className=\"flex flex-col gap-2\">\n {visible.map((s, i) => {\n const snippet = truncate((s.summary || s.content || \"\").replace(/\\s+/g, \" \").trim());\n const title = s.documentName || s.pageTitle || `Source ${s.rank ?? i + 1}`;\n return (\n <li\n key={`${s.id ?? i}`}\n className=\"rounded-md border border-border/60 bg-muted/20 p-2\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"font-medium truncate\">{title}</span>\n {typeof s.similarity === \"number\" && (\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">\n {(s.similarity * 100).toFixed(0)}%\n </span>\n )}\n </div>\n {snippet && (\n <p className=\"mt-1 text-xs text-muted-foreground leading-relaxed\">\n {snippet}\n </p>\n )}\n {s.sourceUrl && (\n <a\n href={s.sourceUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-1 inline-block text-xs text-primary hover:underline\"\n >\n Open source ↗\n </a>\n )}\n </li>\n );\n })}\n </ul>\n\n {sources.length > 3 && (\n <button\n type=\"button\"\n onClick={() => setExpanded((e) => !e)}\n className=\"mt-2 text-xs text-muted-foreground hover:text-foreground\"\n >\n {expanded ? \"Show less\" : `Show ${sources.length - 3} more`}\n </button>\n )}\n </Card>\n );\n}\n\nexport default SearchKnowledgeBaseRenderer;\n","\"use client\";\n\n/**\n * ComponentRenderer — renders a \"legacy\" tool result that ships custom\n * HTML + CSS with Handlebars-style `{{field}}` template variables.\n *\n * Supports single objects and arrays with a responsive grid and a\n * show-more pagination fold. All window access is SSR-guarded.\n */\n\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n useSyncExternalStore,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { processImagesInHtml } from \"../core/image-utils\";\n\nconst MOBILE_BREAKPOINT = 768;\n\nfunction subscribeToResize(cb: () => void) {\n if (typeof window === \"undefined\") return () => {};\n window.addEventListener(\"resize\", cb);\n return () => window.removeEventListener(\"resize\", cb);\n}\n\nfunction getIsMobile() {\n if (typeof window === \"undefined\") return false;\n return window.innerWidth < MOBILE_BREAKPOINT;\n}\n\n/** Props for `ComponentRenderer`. */\nexport interface ComponentRendererProps {\n /** Raw HTML template with `{{field}}` placeholders. */\n htmlCode: string;\n /** Scoped CSS for the template. */\n cssCode: string;\n /** Data payload — object (single render) or array (grid). */\n data: unknown;\n /** Columns on mobile when `data` is an array. Default: 1 */\n mobileGridCols?: number;\n /** Columns on desktop when `data` is an array. Default: 3 */\n desktopGridCols?: number;\n /** Optional interaction tracker. */\n onInteraction?: (params: {\n type: string;\n target: string;\n label: string;\n metadata?: Record<string, unknown>;\n messageId?: string;\n eventId?: string;\n }) => void;\n messageId?: string;\n eventId?: string;\n /** Items per page on mobile (default: 4). */\n mobilePageSize?: number;\n /** Items per page on desktop (default: 4). */\n desktopPageSize?: number;\n}\n\n/**\n * Renders a tool-provided HTML/CSS template against data. Strings such as\n * `{{user.name}}` and `{{#each items}}...{{/each}}` are resolved before\n * insertion.\n */\nexport function ComponentRenderer({\n htmlCode,\n cssCode,\n data,\n mobileGridCols = 1,\n desktopGridCols = 3,\n onInteraction,\n messageId,\n eventId,\n mobilePageSize = 4,\n desktopPageSize = 4,\n}: ComponentRendererProps) {\n const containerId = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const [currentPage, setCurrentPage] = useState(0);\n const isMobile = useSyncExternalStore(\n subscribeToResize,\n getIsMobile,\n () => true\n );\n\n const pageSize = isMobile ? mobilePageSize : desktopPageSize;\n\n const isArray = Array.isArray(data);\n const totalItems = isArray ? (data as unknown[]).length : 1;\n const totalPages = isArray ? Math.ceil(totalItems / pageSize) : 1;\n const hasPagination = isArray && totalItems > pageSize;\n\n useEffect(() => {\n setCurrentPage((p) => Math.min(p, Math.max(0, totalPages - 1)));\n }, [totalPages]);\n\n const displayData =\n isArray && hasPagination\n ? (data as unknown[]).slice(\n currentPage * pageSize,\n (currentPage + 1) * pageSize\n )\n : data;\n\n useEffect(() => {\n if (!containerRef.current) return;\n if (typeof document === \"undefined\") return;\n\n let processedHtml = \"\";\n\n if (Array.isArray(displayData)) {\n const gridId = `grid-${containerId}`;\n const items = displayData\n .map((item, idx) => {\n let rendered = replaceTemplateVariables(htmlCode, item);\n rendered = processImagesInHtml(rendered);\n const globalIndex = currentPage * pageSize + idx;\n return `<div class=\"grid-item\" data-item-index=\"${globalIndex}\">${rendered}</div>`;\n })\n .join(\"\");\n processedHtml = `<div class=\"grid-container\" id=\"${gridId}\">${items}</div>`;\n } else {\n processedHtml = replaceTemplateVariables(htmlCode, displayData);\n processedHtml = processImagesInHtml(processedHtml);\n }\n\n containerRef.current.innerHTML = processedHtml;\n\n const styleId = `component-style-${containerId}`;\n const existingStyle = document.getElementById(styleId);\n if (existingStyle) {\n existingStyle.remove();\n }\n\n let finalCss = cssCode;\n if (Array.isArray(displayData)) {\n const gridCss = `\n#${containerId} .grid-container {\n display: grid;\n grid-template-columns: repeat(${mobileGridCols}, 1fr);\n gap: 1rem;\n width: 100%;\n}\n\n#${containerId} .grid-item {\n width: 100%;\n}\n\n@media (min-width: 768px) {\n #${containerId} .grid-container {\n grid-template-columns: repeat(${desktopGridCols}, 1fr);\n }\n}\n`;\n finalCss = `${cssCode}\\n${gridCss}`;\n }\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = finalCss;\n containerRef.current.appendChild(style);\n\n const images = containerRef.current.querySelectorAll(\"img\");\n images.forEach((img) => {\n if (!img.hasAttribute(\"loading\")) {\n img.setAttribute(\"loading\", \"lazy\");\n }\n });\n\n const links = containerRef.current.querySelectorAll(\"a\");\n links.forEach((link) => {\n link.setAttribute(\"target\", \"_blank\");\n link.setAttribute(\"rel\", \"noopener noreferrer\");\n });\n }, [\n htmlCode,\n cssCode,\n displayData,\n mobileGridCols,\n desktopGridCols,\n containerId,\n currentPage,\n pageSize,\n totalItems,\n totalPages,\n ]);\n\n const handleClick = (e: ReactMouseEvent<HTMLDivElement>) => {\n if (!onInteraction) return;\n const target = e.target as HTMLElement;\n const link = target.closest(\"a\");\n const button = target.closest(\"button\");\n\n if (link?.href) {\n onInteraction({\n type: \"link_click\",\n target: link.href,\n label: link.textContent || link.href,\n metadata: { url: link.href, text: link.textContent },\n messageId,\n eventId,\n });\n } else if (button && !button.hasAttribute(\"data-no-track\")) {\n onInteraction({\n type: \"button_click\",\n target: button.textContent || \"button\",\n label: button.textContent || \"button\",\n metadata: { buttonText: button.textContent },\n messageId,\n eventId,\n });\n }\n };\n\n return (\n <div className=\"component-renderer-wrapper\">\n <div\n ref={containerRef}\n id={containerId}\n className=\"component-render w-full rounded\"\n onClick={handleClick}\n style={{ display: \"block\" }}\n />\n\n {hasPagination && (\n <div className=\"flex items-center justify-center gap-2 mt-4\" dir=\"ltr\">\n <button\n onClick={() => setCurrentPage((p) => Math.max(0, p - 1))}\n disabled={currentPage === 0}\n className=\"px-3 py-1.5 text-sm rounded-md border border-gray-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors\"\n aria-label=\"Previous page\"\n >\n {\"‹\"}\n </button>\n\n <span className=\"text-sm text-gray-600 px-2 tabular-nums\">\n {currentPage + 1} / {totalPages}\n </span>\n\n <button\n onClick={() =>\n setCurrentPage((p) => Math.min(totalPages - 1, p + 1))\n }\n disabled={currentPage >= totalPages - 1}\n className=\"px-3 py-1.5 text-sm rounded-md border border-gray-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors\"\n aria-label=\"Next page\"\n >\n {\"›\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport default ComponentRenderer;\n\n// ---------------------------------------------------------------------------\n// Template engine\n// ---------------------------------------------------------------------------\n\n/**\n * Replace `{{template}}` variables in HTML with actual data values.\n *\n * Supported patterns:\n * • `{{field}}`, `{{nested.field}}`, `{{arr[0].name}}` — interpolation\n * • `{{#each field}}...{{/each}}` — loop over an array\n * • `{{this}}` / `{{this.field}}` — current scope (inside each)\n * • `{{#if field}}...{{/if}}` — render block when field is truthy\n * • `{{#if field}}...{{else}}...{{/if}}` — truthy / falsy branches\n * • `{{#unless field}}...{{/unless}}` — render block when field is falsy\n * • `{{#ifEquals field \"value\"}}...{{/ifEquals}}` — equality branch\n *\n * Truthiness: non-empty array, non-empty string, non-zero number, true.\n */\nfunction replaceTemplateVariables(html: string, data: unknown): string {\n // Control-flow blocks first. Order matters: #each can contain #if, #if can\n // contain #each, so we pass the data through both repeatedly. Two passes\n // covers realistic nesting; the recursion inside each handler covers deeper.\n let processed = processIfBlocks(html, data);\n processed = processUnlessBlocks(processed, data);\n processed = processIfEqualsBlocks(processed, data);\n processed = processEachBlocks(processed, data);\n // Second pass — conditionals emitted from inside an #each may need resolving.\n processed = processIfBlocks(processed, data);\n processed = processUnlessBlocks(processed, data);\n processed = processIfEqualsBlocks(processed, data);\n\n // Strip any leftover block markers we don't recognize (defensive).\n processed = processed.replace(/\\{\\{[#/][^}]+\\}\\}/g, \"\");\n\n processed = processed.replace(/\\{\\{this\\}\\}/g, () =>\n data !== undefined && data !== null ? String(data) : \"\"\n );\n\n processed = processed.replace(/\\{\\{this\\.([^}]+)\\}\\}/g, \"{{$1}}\");\n\n return processed.replace(/\\{\\{([^}]+)\\}\\}/g, (match, path: string) => {\n try {\n const trimmedPath = path.trim();\n const value = getNestedValue(data, trimmedPath);\n\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n } catch {\n return match;\n }\n });\n}\n\n/** Truthy check used by all conditional helpers. */\nfunction isTruthy(value: unknown): boolean {\n if (value === undefined || value === null || value === false) return false;\n if (typeof value === \"string\") return value.length > 0;\n if (typeof value === \"number\") return value !== 0 && !Number.isNaN(value);\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === \"object\") return Object.keys(value as object).length > 0;\n return Boolean(value);\n}\n\n/** Split a conditional body on the first top-level `{{else}}`. */\nfunction splitOnElse(body: string): [string, string | null] {\n // Find the first {{else}} that's NOT nested inside another #if/#each block.\n const re = /\\{\\{(#(?:if|unless|each|ifEquals)\\s+[^}]+|\\/(?:if|unless|each|ifEquals)|else)\\}\\}/g;\n let depth = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body)) !== null) {\n if (m[1].startsWith(\"#\")) depth++;\n else if (m[1].startsWith(\"/\")) depth--;\n else if (m[1] === \"else\" && depth === 0) {\n return [body.slice(0, m.index), body.slice(m.index + \"{{else}}\".length)];\n }\n }\n return [body, null];\n}\n\nfunction processIfBlocks(html: string, data: unknown): string {\n const ifRegex = /\\{\\{#if\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g;\n return html.replace(ifRegex, (_match, field: string, body: string) => {\n const [yes, no] = splitOnElse(body);\n const value = getNestedValue(data, field.trim());\n return isTruthy(value) ? yes : no ?? \"\";\n });\n}\n\nfunction processUnlessBlocks(html: string, data: unknown): string {\n const unlessRegex = /\\{\\{#unless\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/unless\\}\\}/g;\n return html.replace(unlessRegex, (_match, field: string, body: string) => {\n const [no, yes] = splitOnElse(body);\n const value = getNestedValue(data, field.trim());\n return isTruthy(value) ? yes ?? \"\" : no;\n });\n}\n\nfunction processIfEqualsBlocks(html: string, data: unknown): string {\n // {{#ifEquals field \"value\"}} or {{#ifEquals field 'value'}} or {{#ifEquals field 42}}\n const re = /\\{\\{#ifEquals\\s+([^\\s\"'}]+)\\s+(?:\"([^\"]*)\"|'([^']*)'|([^\\s}]+))\\}\\}([\\s\\S]*?)\\{\\{\\/ifEquals\\}\\}/g;\n return html.replace(re, (_match, field: string, dq: string, sq: string, raw: string, body: string) => {\n const [yes, no] = splitOnElse(body);\n const expected = dq ?? sq ?? raw;\n const value = getNestedValue(data, field.trim());\n const matches = String(value) === String(expected);\n return matches ? yes : no ?? \"\";\n });\n}\n\nfunction processEachBlocks(html: string, data: unknown): string {\n const eachRegex = /\\{\\{#each\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/each\\}\\}/g;\n\n return html.replace(eachRegex, (_match, field: string, content: string) => {\n const trimmedField = field.trim();\n const array = getNestedValue(data, trimmedField);\n if (!Array.isArray(array)) return \"\";\n\n return array\n .map((item) => {\n // Process nested control flow in this item's scope.\n let itemHtml = processEachBlocks(content, item);\n itemHtml = processIfBlocks(itemHtml, item);\n itemHtml = processUnlessBlocks(itemHtml, item);\n itemHtml = processIfEqualsBlocks(itemHtml, item);\n\n if (typeof item !== \"object\" || item === null) {\n itemHtml = itemHtml.replace(/\\{\\{this\\}\\}/g, String(item));\n return itemHtml;\n }\n\n itemHtml = itemHtml.replace(/\\{\\{this\\.([^}]+)\\}\\}/g, \"{{$1}}\");\n itemHtml = itemHtml.replace(/\\{\\{([^}]+)\\}\\}/g, (m, path: string) => {\n const trimmedPath = path.trim();\n if (trimmedPath.startsWith(\"#\") || trimmedPath.startsWith(\"/\"))\n return m;\n const value = getNestedValue(item, trimmedPath);\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n });\n\n return itemHtml;\n })\n .join(\"\");\n });\n}\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n if (!path || obj === null || obj === undefined) return undefined;\n\n const parts = path.split(/\\.(?![^[]*\\])/);\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n\n const arrayMatch = part.match(/^([^[]+)\\[([^\\]]+)\\]$/);\n if (arrayMatch) {\n const [, key, index] = arrayMatch;\n current = (current as Record<string, unknown>)[key];\n if (Array.isArray(current)) {\n current = current[parseInt(index, 10)];\n }\n } else {\n current = (current as Record<string, unknown>)[part];\n }\n }\n\n return current;\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { ChatContext } from \"../providers/ChatContext\";\nimport type { ChatConfig, ChatEventCallbacks } from \"../core/types\";\n\n/**\n * Read chat event callbacks from ChatContext if available, otherwise return\n * an empty object. Safe to call from components that may render outside a\n * ChatProvider (e.g. standalone tool previews).\n */\nexport function useSafeChatCallbacks(): ChatEventCallbacks {\n\tconst ctx = useContext(ChatContext);\n\treturn ctx?.callbacks ?? {};\n}\n\n/**\n * Read the chat config (projectId, apiEndpoint, apiKey, clientName) from\n * ChatContext if available. Returns `undefined` when the component renders\n * outside a ChatProvider so callers can decide how to degrade (e.g. tool\n * result renderers in standalone previews skip auth-required actions).\n */\nexport function useSafeChatConfig(): ChatConfig | undefined {\n\tconst ctx = useContext(ChatContext);\n\treturn ctx?.config;\n}\n","\"use client\";\n\n/**\n * Built-in tool renderer registry.\n *\n * The `ToolRenderer` router consults these maps after slot overrides and\n * before falling back to a generic JSON preview.\n */\n\nimport type { ComponentType } from \"react\";\nimport type { ToolRendererProps } from \"../core/types\";\nimport { SearchKnowledgeBaseRenderer } from \"./SearchKnowledgeBaseRenderer\";\n\n/**\n * Map of built-in renderers keyed by the tool result's `uiRenderMode`.\n *\n * Entries are populated lazily by `ToolRenderer` (via `React.lazy`) so the\n * heavy renderers (recharts, JSON-render catalog) don't end up in the core\n * bundle unless used. This map is intentionally empty at module scope — look\n * at `ToolRenderer.tsx` for the actual dispatch logic.\n */\nexport const BUILTIN_TOOL_RENDERERS: Record<\n string,\n ComponentType<ToolRendererProps> | null\n> = {\n visualization: null,\n json_render: null,\n legacy: null,\n preset: null,\n none: null,\n};\n\n/**\n * Built-in renderers addressed by tool *name* (not render mode).\n *\n * A `null` value signals \"render nothing\" — useful for tools whose side\n * effects are handled elsewhere (e.g. `requestHumanChat` is consumed by the\n * `LiveChatProvider` and must not produce UI inside the message stream).\n */\nexport const BUILTIN_NAMED_RENDERERS: Record<\n string,\n ComponentType<ToolRendererProps> | null\n> = {\n requestHumanChat: null,\n // Hidden by default — knowledge-base searches are context for the assistant,\n // not content for the user. Opt in via:\n // slots: { tools: { searchKnowledgeBase: SearchKnowledgeBaseRenderer } }\n searchKnowledgeBase: null,\n};\n// Keep the component reachable even though the default is null.\nvoid SearchKnowledgeBaseRenderer;\n","\"use client\";\n\n/**\n * ToolRenderer — the main dispatcher for tool invocations in the chat stream.\n *\n * Resolution order:\n * 1. `slots.tools[toolName]` — per-tool-name slot override\n * 2. `slots.toolRenderers[result.uiRenderMode]` — per-render-mode slot override\n * 3. `BUILTIN_NAMED_RENDERERS[toolName]` — special named built-ins\n * 4. `BUILTIN_TOOL_RENDERERS[result.uiRenderMode]` — built-in mode dispatch\n * 5. Fallback — clean JSON preview inside a Card\n *\n * Heavy renderers (`VisualizationRenderer`, `JsonRenderResult`) are loaded\n * lazily via `React.lazy` + `Suspense` to keep the core bundle small.\n */\n\nimport {\n lazy,\n Suspense,\n useEffect,\n useMemo,\n type ComponentType,\n} from \"react\";\nimport { useSlots } from \"../providers/SlotsContext\";\nimport { Card } from \"../ui/card\";\nimport { Spinner } from \"../ui/spinner\";\nimport type {\n ComponentAction,\n ToolRendererProps,\n ToolResult,\n} from \"../core/types\";\n// ToolRenderer may be rendered outside a ChatContext (e.g. standalone\n// previews), so we read the context defensively via a safe hook.\nimport { useSafeChatCallbacks, useSafeChatConfig } from \"./useSafeChatCallbacks\";\nimport {\n BUILTIN_NAMED_RENDERERS,\n BUILTIN_TOOL_RENDERERS,\n} from \"./tool-registry\";\nimport { ComponentRenderer } from \"./ComponentRenderer\";\n\n// ---------------------------------------------------------------------------\n// Lazy renderers\n// ---------------------------------------------------------------------------\n\nconst LazyVisualization = lazy(() =>\n import(\"./VisualizationRenderer\").then((m) => ({\n default: m.VisualizationRenderer,\n }))\n);\n\nconst LazyJsonRender = lazy(() =>\n import(\"../json-render/JsonRenderResult\").then((m) => ({\n default: m.JsonRenderResult as unknown as ComponentType<Record<string, unknown>>,\n }))\n);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Return the best display payload for a tool result, preferring `_displayData`\n * (which the server strips before sending back to the LLM) over `data`.\n */\nfunction getDisplayData(result: ToolResult | undefined): unknown {\n if (!result) return undefined;\n if (result._displayData !== undefined) return result._displayData;\n return result.data;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Default (fallback) renderers\n// ---------------------------------------------------------------------------\n\nfunction LoadingFallback({ text }: { text?: string }) {\n return (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n <span>{text || \"Working...\"}</span>\n </div>\n );\n}\n\nfunction PresetPreview(props: ToolRendererProps) {\n const payload = getDisplayData(props.result);\n if (payload === undefined || payload === null) return null;\n return (\n <Card className=\"p-3\">\n <pre className=\"text-xs overflow-x-auto whitespace-pre-wrap break-words\">\n {safeStringify(payload)}\n </pre>\n </Card>\n );\n}\n\nfunction VisualizationWrapper(props: ToolRendererProps) {\n const payload = getDisplayData(props.result);\n // Accept either a full spec or `{ spec: ... }`.\n const spec =\n payload && typeof payload === \"object\" && \"type\" in (payload as object)\n ? (payload as Record<string, unknown>)\n : (payload as { spec?: Record<string, unknown> })?.spec;\n if (!spec) return null;\n return (\n <Suspense fallback={<LoadingFallback text={props.result?.loadingText} />}>\n {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}\n <LazyVisualization spec={spec as any} />\n </Suspense>\n );\n}\n\nfunction JsonRenderWrapper(props: ToolRendererProps) {\n const spec = props.result?.jsonRenderSpec;\n const payload = getDisplayData(props.result);\n // Pull apiKey from the chat config so `call_api` actions in the spec\n // (e.g. form-submit buttons hitting /api/kb/form-submit) can attach the\n // project's Bearer token. Without this, third-party-domain embeds hit\n // 401 on submit — the matching headline bug.\n const chatConfig = useSafeChatConfig();\n if (!spec) return null;\n return (\n <Suspense fallback={<LoadingFallback text={props.result?.loadingText} />}>\n <LazyJsonRender\n spec={spec}\n data={payload}\n onSendMessage={props.onSendMessage}\n onAction={props.onAction}\n apiKey={chatConfig?.apiKey}\n apiEndpoint={chatConfig?.apiEndpoint}\n />\n </Suspense>\n );\n}\n\nfunction LegacyWrapper(props: ToolRendererProps) {\n const result = props.result;\n const payload = getDisplayData(result);\n const config = result?.customComponent;\n // `customComponent` in core/types is declared as `string`, but when used by\n // the legacy render mode the server inlines the `{ htmlCode, cssCode, ... }`\n // object. Widen the type locally.\n const cfg =\n typeof config === \"object\" && config !== null\n ? (config as {\n htmlCode?: string;\n cssCode?: string;\n mobileGridCols?: number;\n desktopGridCols?: number;\n mobilePageSize?: number;\n desktopPageSize?: number;\n })\n : null;\n if (!cfg?.htmlCode) return null;\n\n return (\n <ComponentRenderer\n htmlCode={cfg.htmlCode}\n cssCode={cfg.cssCode || \"\"}\n data={payload}\n mobileGridCols={cfg.mobileGridCols}\n desktopGridCols={cfg.desktopGridCols}\n mobilePageSize={cfg.mobilePageSize}\n desktopPageSize={cfg.desktopPageSize}\n />\n );\n}\n\nfunction FallbackPreview(props: ToolRendererProps) {\n const payload = getDisplayData(props.result);\n if (payload === undefined) return null;\n return (\n <Card className=\"p-3 bg-muted/30\">\n <pre className=\"text-xs overflow-x-auto whitespace-pre-wrap break-words\">\n {safeStringify(payload)}\n </pre>\n </Card>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Router\n// ---------------------------------------------------------------------------\n\n/**\n * Main tool renderer. Place one of these per tool invocation inside the\n * assistant message stream.\n */\ninterface PublicSlotMap {\n loader?: ComponentType<{ text?: string }>;\n tools?: Record<string, ComponentType<ToolRendererProps>>;\n toolRenderers?: Record<string, ComponentType<ToolRendererProps>>;\n}\n\n// Known render modes — used to detect tool-name typos in slots.toolRenderers.\nconst KNOWN_RENDER_MODES = new Set([\n \"visualization\",\n \"json_render\",\n \"json\",\n \"legacy\",\n \"display\",\n \"preset\",\n \"text\",\n \"none\",\n \"hidden\",\n]);\n\n// Track tool names we've already warned about to avoid log spam.\nconst warnedToolNames = new Set<string>();\n\nexport function ToolRenderer(props: ToolRendererProps) {\n const { toolName, state, result } = props;\n const slots = useSlots() as unknown as PublicSlotMap;\n const callbacks = useSafeChatCallbacks();\n\n // ----- Fire analytics callbacks -----\n useEffect(() => {\n if (state === \"output-available\" && result) {\n (callbacks as { onToolResult?: (...args: unknown[]) => void } | undefined)?.onToolResult?.(toolName, result, result.uiRenderMode);\n }\n }, [state, toolName, result, callbacks]);\n\n // ----- Dev warning: did the caller confuse `tools` and `toolRenderers`? -----\n // `toolRenderers` is keyed by render MODE. If a key looks like a tool name\n // (not a known mode) AND there's a tool result with that name, it's almost\n // certainly a mistake — the override will never fire.\n useEffect(() => {\n if (process.env.NODE_ENV === \"production\") return;\n const modeKeys = Object.keys(slots.toolRenderers || {});\n for (const key of modeKeys) {\n if (!KNOWN_RENDER_MODES.has(key) && key === toolName && !warnedToolNames.has(key)) {\n warnedToolNames.add(key);\n console.warn(\n `[aigentyc-chat-sdk] slots.toolRenderers[\"${key}\"] looks like a tool name, ` +\n `but toolRenderers is keyed by render MODE (visualization | json_render | ` +\n `legacy | preset | text). Did you mean slots.tools[\"${key}\"]?`,\n );\n }\n }\n }, [slots.toolRenderers, toolName]);\n\n // Wrap onAction to also forward to callbacks.onToolAction.\n const onAction = useMemo(() => {\n const userOnAction = props.onAction;\n return (action: ComponentAction, itemData?: unknown) => {\n (callbacks as { onToolAction?: (...args: unknown[]) => void } | undefined)?.onToolAction?.(action, itemData);\n userOnAction?.(action);\n };\n }, [callbacks, props.onAction]);\n\n // Build a prop-forwarding wrapper that swaps `onAction`.\n const forwardedProps: ToolRendererProps = { ...props, onAction };\n\n // ----- Pending / in-flight states -----\n if (state === \"partial-call\" || state === \"call\") {\n const slotLoader = (slots as { loader?: ComponentType<unknown> }).loader;\n if (slotLoader) {\n const L = slotLoader as ComponentType<{ text?: string }>;\n return <L text={result?.loadingText} />;\n }\n return <LoadingFallback text={result?.loadingText} />;\n }\n\n // Output-available — nothing to show if the result explicitly hides itself\n const mode = (result?.uiRenderMode as string | undefined) ?? \"preset\";\n if (mode === \"none\" || mode === \"hidden\") {\n // Still check named overrides in case a host wants to render a\n // side-effect-y tool.\n const named = slots.tools?.[toolName];\n if (named) {\n return renderWithDefault(named, forwardedProps, FallbackPreview);\n }\n return null;\n }\n\n // 1. per-tool slot override\n const toolSlot = slots.tools?.[toolName];\n if (toolSlot) {\n return renderWithDefault(toolSlot, forwardedProps, pickDefaultForMode(mode));\n }\n\n // 2. per-render-mode slot override\n const modeSlot = slots.toolRenderers?.[mode];\n if (modeSlot) {\n return renderWithDefault(modeSlot, forwardedProps, pickDefaultForMode(mode));\n }\n\n // 3. named built-in\n const namedBuiltin = BUILTIN_NAMED_RENDERERS[toolName];\n if (namedBuiltin === null && toolName in BUILTIN_NAMED_RENDERERS) {\n // explicit \"render nothing\" for this tool\n return null;\n }\n if (namedBuiltin) {\n const N = namedBuiltin;\n return <N {...forwardedProps} />;\n }\n\n // 4. built-in by render mode\n switch (mode) {\n case \"visualization\":\n return <VisualizationWrapper {...forwardedProps} />;\n case \"json_render\":\n case \"json\":\n return <JsonRenderWrapper {...forwardedProps} />;\n case \"legacy\":\n case \"display\":\n return <LegacyWrapper {...forwardedProps} />;\n case \"preset\":\n case \"text\":\n return <PresetPreview {...forwardedProps} />;\n default:\n // 5. fallback JSON card\n return <FallbackPreview {...forwardedProps} />;\n }\n}\n\nexport default ToolRenderer;\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\n/**\n * Render a slot override and inject the matching `DefaultComponent` so the\n * override can fall back to the built-in rendering.\n */\nfunction renderWithDefault(\n Override: ComponentType<ToolRendererProps & { DefaultComponent?: ComponentType<ToolRendererProps> }>,\n props: ToolRendererProps,\n Default: ComponentType<ToolRendererProps>\n) {\n return <Override {...props} DefaultComponent={Default} />;\n}\n\nfunction pickDefaultForMode(mode: string): ComponentType<ToolRendererProps> {\n switch (mode) {\n case \"visualization\":\n return VisualizationWrapper;\n case \"json_render\":\n case \"json\":\n return JsonRenderWrapper;\n case \"legacy\":\n case \"display\":\n return LegacyWrapper;\n case \"preset\":\n case \"text\":\n return PresetPreview;\n default:\n return FallbackPreview;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports for convenience\n// ---------------------------------------------------------------------------\n\nexport type { ToolRendererProps, ToolResult, ComponentAction };\n"]}
1
+ {"version":3,"sources":["../src/tools/SearchKnowledgeBaseRenderer.tsx","../src/tools/ComponentRenderer.tsx","../src/tools/useSafeChatCallbacks.ts","../src/tools/tool-registry.ts","../src/tools/ToolRenderer.tsx"],"names":["useState","jsxs","jsx","useEffect"],"mappings":"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","file":"chunk-4DC55YI3.js","sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Card } from \"../ui/card\";\nimport type { ToolRendererProps } from \"../core/types\";\n\ninterface KbSource {\n rank?: number;\n id?: number | string;\n content?: string;\n documentName?: string;\n sourceUrl?: string | null;\n similarity?: number;\n pageTitle?: string | null;\n summary?: string | null;\n relevance?: string;\n}\n\ninterface KbResult {\n found?: boolean;\n totalResults?: number;\n generatedQueries?: string[];\n sources?: KbSource[];\n}\n\nfunction truncate(text: string, max = 220) {\n if (text.length <= max) return text;\n return text.slice(0, max).trimEnd() + \"…\";\n}\n\nexport function SearchKnowledgeBaseRenderer(props: ToolRendererProps) {\n const data = (props.result?._displayData ?? props.result?.data) as KbResult | undefined;\n const [expanded, setExpanded] = useState(false);\n\n if (!data || !data.found || !Array.isArray(data.sources) || data.sources.length === 0) {\n return null;\n }\n\n const sources = data.sources;\n const visible = expanded ? sources : sources.slice(0, 3);\n\n return (\n <Card className=\"p-3 text-sm\">\n <div className=\"mb-2 flex items-center justify-between text-xs text-muted-foreground\">\n <span>\n Found <strong className=\"text-foreground\">{data.totalResults ?? sources.length}</strong>{\" \"}\n source{(data.totalResults ?? sources.length) === 1 ? \"\" : \"s\"}\n {data.generatedQueries?.length\n ? ` for \"${data.generatedQueries.join(\", \")}\"`\n : \"\"}\n </span>\n </div>\n\n <ul className=\"flex flex-col gap-2\">\n {visible.map((s, i) => {\n const snippet = truncate((s.summary || s.content || \"\").replace(/\\s+/g, \" \").trim());\n const title = s.documentName || s.pageTitle || `Source ${s.rank ?? i + 1}`;\n return (\n <li\n key={`${s.id ?? i}`}\n className=\"rounded-md border border-border/60 bg-muted/20 p-2\"\n >\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"font-medium truncate\">{title}</span>\n {typeof s.similarity === \"number\" && (\n <span className=\"shrink-0 text-[10px] text-muted-foreground\">\n {(s.similarity * 100).toFixed(0)}%\n </span>\n )}\n </div>\n {snippet && (\n <p className=\"mt-1 text-xs text-muted-foreground leading-relaxed\">\n {snippet}\n </p>\n )}\n {s.sourceUrl && (\n <a\n href={s.sourceUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mt-1 inline-block text-xs text-primary hover:underline\"\n >\n Open source ↗\n </a>\n )}\n </li>\n );\n })}\n </ul>\n\n {sources.length > 3 && (\n <button\n type=\"button\"\n onClick={() => setExpanded((e) => !e)}\n className=\"mt-2 text-xs text-muted-foreground hover:text-foreground\"\n >\n {expanded ? \"Show less\" : `Show ${sources.length - 3} more`}\n </button>\n )}\n </Card>\n );\n}\n\nexport default SearchKnowledgeBaseRenderer;\n","\"use client\";\n\n/**\n * ComponentRenderer — renders a \"legacy\" tool result that ships custom\n * HTML + CSS with Handlebars-style `{{field}}` template variables.\n *\n * Supports single objects and arrays with a responsive grid and a\n * show-more pagination fold. All window access is SSR-guarded.\n */\n\nimport {\n useEffect,\n useId,\n useRef,\n useState,\n useSyncExternalStore,\n type MouseEvent as ReactMouseEvent,\n} from \"react\";\nimport { processImagesInHtml } from \"../core/image-utils\";\n\nconst MOBILE_BREAKPOINT = 768;\n\nfunction subscribeToResize(cb: () => void) {\n if (typeof window === \"undefined\") return () => {};\n window.addEventListener(\"resize\", cb);\n return () => window.removeEventListener(\"resize\", cb);\n}\n\nfunction getIsMobile() {\n if (typeof window === \"undefined\") return false;\n return window.innerWidth < MOBILE_BREAKPOINT;\n}\n\n/** Props for `ComponentRenderer`. */\nexport interface ComponentRendererProps {\n /** Raw HTML template with `{{field}}` placeholders. */\n htmlCode: string;\n /** Scoped CSS for the template. */\n cssCode: string;\n /** Data payload — object (single render) or array (grid). */\n data: unknown;\n /** Columns on mobile when `data` is an array. Default: 1 */\n mobileGridCols?: number;\n /** Columns on desktop when `data` is an array. Default: 3 */\n desktopGridCols?: number;\n /** Optional interaction tracker. */\n onInteraction?: (params: {\n type: string;\n target: string;\n label: string;\n metadata?: Record<string, unknown>;\n messageId?: string;\n eventId?: string;\n }) => void;\n messageId?: string;\n eventId?: string;\n /** Items per page on mobile (default: 4). */\n mobilePageSize?: number;\n /** Items per page on desktop (default: 4). */\n desktopPageSize?: number;\n}\n\n/**\n * Renders a tool-provided HTML/CSS template against data. Strings such as\n * `{{user.name}}` and `{{#each items}}...{{/each}}` are resolved before\n * insertion.\n */\nexport function ComponentRenderer({\n htmlCode,\n cssCode,\n data,\n mobileGridCols = 1,\n desktopGridCols = 3,\n onInteraction,\n messageId,\n eventId,\n mobilePageSize = 4,\n desktopPageSize = 4,\n}: ComponentRendererProps) {\n const containerId = useId();\n const containerRef = useRef<HTMLDivElement>(null);\n const [currentPage, setCurrentPage] = useState(0);\n const isMobile = useSyncExternalStore(\n subscribeToResize,\n getIsMobile,\n () => true\n );\n\n const pageSize = isMobile ? mobilePageSize : desktopPageSize;\n\n const isArray = Array.isArray(data);\n const totalItems = isArray ? (data as unknown[]).length : 1;\n const totalPages = isArray ? Math.ceil(totalItems / pageSize) : 1;\n const hasPagination = isArray && totalItems > pageSize;\n\n useEffect(() => {\n setCurrentPage((p) => Math.min(p, Math.max(0, totalPages - 1)));\n }, [totalPages]);\n\n const displayData =\n isArray && hasPagination\n ? (data as unknown[]).slice(\n currentPage * pageSize,\n (currentPage + 1) * pageSize\n )\n : data;\n\n useEffect(() => {\n if (!containerRef.current) return;\n if (typeof document === \"undefined\") return;\n\n let processedHtml = \"\";\n\n if (Array.isArray(displayData)) {\n const gridId = `grid-${containerId}`;\n const items = displayData\n .map((item, idx) => {\n let rendered = replaceTemplateVariables(htmlCode, item);\n rendered = processImagesInHtml(rendered);\n const globalIndex = currentPage * pageSize + idx;\n return `<div class=\"grid-item\" data-item-index=\"${globalIndex}\">${rendered}</div>`;\n })\n .join(\"\");\n processedHtml = `<div class=\"grid-container\" id=\"${gridId}\">${items}</div>`;\n } else {\n processedHtml = replaceTemplateVariables(htmlCode, displayData);\n processedHtml = processImagesInHtml(processedHtml);\n }\n\n containerRef.current.innerHTML = processedHtml;\n\n const styleId = `component-style-${containerId}`;\n const existingStyle = document.getElementById(styleId);\n if (existingStyle) {\n existingStyle.remove();\n }\n\n let finalCss = cssCode;\n if (Array.isArray(displayData)) {\n const gridCss = `\n#${containerId} .grid-container {\n display: grid;\n grid-template-columns: repeat(${mobileGridCols}, 1fr);\n gap: 1rem;\n width: 100%;\n}\n\n#${containerId} .grid-item {\n width: 100%;\n}\n\n@media (min-width: 768px) {\n #${containerId} .grid-container {\n grid-template-columns: repeat(${desktopGridCols}, 1fr);\n }\n}\n`;\n finalCss = `${cssCode}\\n${gridCss}`;\n }\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = finalCss;\n containerRef.current.appendChild(style);\n\n const images = containerRef.current.querySelectorAll(\"img\");\n images.forEach((img) => {\n if (!img.hasAttribute(\"loading\")) {\n img.setAttribute(\"loading\", \"lazy\");\n }\n });\n\n const links = containerRef.current.querySelectorAll(\"a\");\n links.forEach((link) => {\n link.setAttribute(\"target\", \"_blank\");\n link.setAttribute(\"rel\", \"noopener noreferrer\");\n });\n }, [\n htmlCode,\n cssCode,\n displayData,\n mobileGridCols,\n desktopGridCols,\n containerId,\n currentPage,\n pageSize,\n totalItems,\n totalPages,\n ]);\n\n const handleClick = (e: ReactMouseEvent<HTMLDivElement>) => {\n if (!onInteraction) return;\n const target = e.target as HTMLElement;\n const link = target.closest(\"a\");\n const button = target.closest(\"button\");\n\n if (link?.href) {\n onInteraction({\n type: \"link_click\",\n target: link.href,\n label: link.textContent || link.href,\n metadata: { url: link.href, text: link.textContent },\n messageId,\n eventId,\n });\n } else if (button && !button.hasAttribute(\"data-no-track\")) {\n onInteraction({\n type: \"button_click\",\n target: button.textContent || \"button\",\n label: button.textContent || \"button\",\n metadata: { buttonText: button.textContent },\n messageId,\n eventId,\n });\n }\n };\n\n return (\n <div className=\"component-renderer-wrapper\">\n <div\n ref={containerRef}\n id={containerId}\n className=\"component-render w-full rounded\"\n onClick={handleClick}\n style={{ display: \"block\" }}\n />\n\n {hasPagination && (\n <div className=\"flex items-center justify-center gap-2 mt-4\" dir=\"ltr\">\n <button\n onClick={() => setCurrentPage((p) => Math.max(0, p - 1))}\n disabled={currentPage === 0}\n className=\"px-3 py-1.5 text-sm rounded-md border border-gray-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors\"\n aria-label=\"Previous page\"\n >\n {\"‹\"}\n </button>\n\n <span className=\"text-sm text-gray-600 px-2 tabular-nums\">\n {currentPage + 1} / {totalPages}\n </span>\n\n <button\n onClick={() =>\n setCurrentPage((p) => Math.min(totalPages - 1, p + 1))\n }\n disabled={currentPage >= totalPages - 1}\n className=\"px-3 py-1.5 text-sm rounded-md border border-gray-300 disabled:opacity-40 disabled:cursor-not-allowed hover:bg-gray-100 transition-colors\"\n aria-label=\"Next page\"\n >\n {\"›\"}\n </button>\n </div>\n )}\n </div>\n );\n}\n\nexport default ComponentRenderer;\n\n// ---------------------------------------------------------------------------\n// Template engine\n// ---------------------------------------------------------------------------\n\n/**\n * Replace `{{template}}` variables in HTML with actual data values.\n *\n * Supported patterns:\n * • `{{field}}`, `{{nested.field}}`, `{{arr[0].name}}` — interpolation\n * • `{{#each field}}...{{/each}}` — loop over an array\n * • `{{this}}` / `{{this.field}}` — current scope (inside each)\n * • `{{#if field}}...{{/if}}` — render block when field is truthy\n * • `{{#if field}}...{{else}}...{{/if}}` — truthy / falsy branches\n * • `{{#unless field}}...{{/unless}}` — render block when field is falsy\n * • `{{#ifEquals field \"value\"}}...{{/ifEquals}}` — equality branch\n *\n * Truthiness: non-empty array, non-empty string, non-zero number, true.\n */\nfunction replaceTemplateVariables(html: string, data: unknown): string {\n // Control-flow blocks first. Order matters: #each can contain #if, #if can\n // contain #each, so we pass the data through both repeatedly. Two passes\n // covers realistic nesting; the recursion inside each handler covers deeper.\n let processed = processIfBlocks(html, data);\n processed = processUnlessBlocks(processed, data);\n processed = processIfEqualsBlocks(processed, data);\n processed = processEachBlocks(processed, data);\n // Second pass — conditionals emitted from inside an #each may need resolving.\n processed = processIfBlocks(processed, data);\n processed = processUnlessBlocks(processed, data);\n processed = processIfEqualsBlocks(processed, data);\n\n // Strip any leftover block markers we don't recognize (defensive).\n processed = processed.replace(/\\{\\{[#/][^}]+\\}\\}/g, \"\");\n\n processed = processed.replace(/\\{\\{this\\}\\}/g, () =>\n data !== undefined && data !== null ? String(data) : \"\"\n );\n\n processed = processed.replace(/\\{\\{this\\.([^}]+)\\}\\}/g, \"{{$1}}\");\n\n return processed.replace(/\\{\\{([^}]+)\\}\\}/g, (match, path: string) => {\n try {\n const trimmedPath = path.trim();\n const value = getNestedValue(data, trimmedPath);\n\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n } catch {\n return match;\n }\n });\n}\n\n/** Truthy check used by all conditional helpers. */\nfunction isTruthy(value: unknown): boolean {\n if (value === undefined || value === null || value === false) return false;\n if (typeof value === \"string\") return value.length > 0;\n if (typeof value === \"number\") return value !== 0 && !Number.isNaN(value);\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === \"object\") return Object.keys(value as object).length > 0;\n return Boolean(value);\n}\n\n/** Split a conditional body on the first top-level `{{else}}`. */\nfunction splitOnElse(body: string): [string, string | null] {\n // Find the first {{else}} that's NOT nested inside another #if/#each block.\n const re = /\\{\\{(#(?:if|unless|each|ifEquals)\\s+[^}]+|\\/(?:if|unless|each|ifEquals)|else)\\}\\}/g;\n let depth = 0;\n let m: RegExpExecArray | null;\n while ((m = re.exec(body)) !== null) {\n if (m[1].startsWith(\"#\")) depth++;\n else if (m[1].startsWith(\"/\")) depth--;\n else if (m[1] === \"else\" && depth === 0) {\n return [body.slice(0, m.index), body.slice(m.index + \"{{else}}\".length)];\n }\n }\n return [body, null];\n}\n\nfunction processIfBlocks(html: string, data: unknown): string {\n const ifRegex = /\\{\\{#if\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/if\\}\\}/g;\n return html.replace(ifRegex, (_match, field: string, body: string) => {\n const [yes, no] = splitOnElse(body);\n const value = getNestedValue(data, field.trim());\n return isTruthy(value) ? yes : no ?? \"\";\n });\n}\n\nfunction processUnlessBlocks(html: string, data: unknown): string {\n const unlessRegex = /\\{\\{#unless\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/unless\\}\\}/g;\n return html.replace(unlessRegex, (_match, field: string, body: string) => {\n const [no, yes] = splitOnElse(body);\n const value = getNestedValue(data, field.trim());\n return isTruthy(value) ? yes ?? \"\" : no;\n });\n}\n\nfunction processIfEqualsBlocks(html: string, data: unknown): string {\n // {{#ifEquals field \"value\"}} or {{#ifEquals field 'value'}} or {{#ifEquals field 42}}\n const re = /\\{\\{#ifEquals\\s+([^\\s\"'}]+)\\s+(?:\"([^\"]*)\"|'([^']*)'|([^\\s}]+))\\}\\}([\\s\\S]*?)\\{\\{\\/ifEquals\\}\\}/g;\n return html.replace(re, (_match, field: string, dq: string, sq: string, raw: string, body: string) => {\n const [yes, no] = splitOnElse(body);\n const expected = dq ?? sq ?? raw;\n const value = getNestedValue(data, field.trim());\n const matches = String(value) === String(expected);\n return matches ? yes : no ?? \"\";\n });\n}\n\nfunction processEachBlocks(html: string, data: unknown): string {\n const eachRegex = /\\{\\{#each\\s+([^}]+)\\}\\}([\\s\\S]*?)\\{\\{\\/each\\}\\}/g;\n\n return html.replace(eachRegex, (_match, field: string, content: string) => {\n const trimmedField = field.trim();\n const array = getNestedValue(data, trimmedField);\n if (!Array.isArray(array)) return \"\";\n\n return array\n .map((item) => {\n // Process nested control flow in this item's scope.\n let itemHtml = processEachBlocks(content, item);\n itemHtml = processIfBlocks(itemHtml, item);\n itemHtml = processUnlessBlocks(itemHtml, item);\n itemHtml = processIfEqualsBlocks(itemHtml, item);\n\n if (typeof item !== \"object\" || item === null) {\n itemHtml = itemHtml.replace(/\\{\\{this\\}\\}/g, String(item));\n return itemHtml;\n }\n\n itemHtml = itemHtml.replace(/\\{\\{this\\.([^}]+)\\}\\}/g, \"{{$1}}\");\n itemHtml = itemHtml.replace(/\\{\\{([^}]+)\\}\\}/g, (m, path: string) => {\n const trimmedPath = path.trim();\n if (trimmedPath.startsWith(\"#\") || trimmedPath.startsWith(\"/\"))\n return m;\n const value = getNestedValue(item, trimmedPath);\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"object\") return JSON.stringify(value);\n return String(value);\n });\n\n return itemHtml;\n })\n .join(\"\");\n });\n}\n\nfunction getNestedValue(obj: unknown, path: string): unknown {\n if (!path || obj === null || obj === undefined) return undefined;\n\n const parts = path.split(/\\.(?![^[]*\\])/);\n let current: unknown = obj;\n\n for (const part of parts) {\n if (current === null || current === undefined) return undefined;\n\n const arrayMatch = part.match(/^([^[]+)\\[([^\\]]+)\\]$/);\n if (arrayMatch) {\n const [, key, index] = arrayMatch;\n current = (current as Record<string, unknown>)[key];\n if (Array.isArray(current)) {\n current = current[parseInt(index, 10)];\n }\n } else {\n current = (current as Record<string, unknown>)[part];\n }\n }\n\n return current;\n}\n","\"use client\";\n\nimport { useContext } from \"react\";\nimport { ChatContext } from \"../providers/ChatContext\";\nimport type { ChatConfig, ChatEventCallbacks } from \"../core/types\";\n\n/**\n * Read chat event callbacks from ChatContext if available, otherwise return\n * an empty object. Safe to call from components that may render outside a\n * ChatProvider (e.g. standalone tool previews).\n */\nexport function useSafeChatCallbacks(): ChatEventCallbacks {\n\tconst ctx = useContext(ChatContext);\n\treturn ctx?.callbacks ?? {};\n}\n\n/**\n * Read the chat config (projectId, apiEndpoint, apiKey, clientName) from\n * ChatContext if available. Returns `undefined` when the component renders\n * outside a ChatProvider so callers can decide how to degrade (e.g. tool\n * result renderers in standalone previews skip auth-required actions).\n */\nexport function useSafeChatConfig(): ChatConfig | undefined {\n\tconst ctx = useContext(ChatContext);\n\treturn ctx?.config;\n}\n","\"use client\";\n\n/**\n * Built-in tool renderer registry.\n *\n * The `ToolRenderer` router consults these maps after slot overrides and\n * before falling back to a generic JSON preview.\n */\n\nimport type { ComponentType } from \"react\";\nimport type { ToolRendererProps } from \"../core/types\";\nimport { SearchKnowledgeBaseRenderer } from \"./SearchKnowledgeBaseRenderer\";\n\n/**\n * Map of built-in renderers keyed by the tool result's `uiRenderMode`.\n *\n * Entries are populated lazily by `ToolRenderer` (via `React.lazy`) so the\n * heavy renderers (recharts, JSON-render catalog) don't end up in the core\n * bundle unless used. This map is intentionally empty at module scope — look\n * at `ToolRenderer.tsx` for the actual dispatch logic.\n */\nexport const BUILTIN_TOOL_RENDERERS: Record<\n string,\n ComponentType<ToolRendererProps> | null\n> = {\n visualization: null,\n json_render: null,\n legacy: null,\n preset: null,\n none: null,\n};\n\n/**\n * Built-in renderers addressed by tool *name* (not render mode).\n *\n * A `null` value signals \"render nothing\" — useful for tools whose side\n * effects are handled elsewhere (e.g. `requestHumanChat` is consumed by the\n * `LiveChatProvider` and must not produce UI inside the message stream).\n */\nexport const BUILTIN_NAMED_RENDERERS: Record<\n string,\n ComponentType<ToolRendererProps> | null\n> = {\n requestHumanChat: null,\n // Hidden by default — knowledge-base searches are context for the assistant,\n // not content for the user. Opt in via:\n // slots: { tools: { searchKnowledgeBase: SearchKnowledgeBaseRenderer } }\n searchKnowledgeBase: null,\n};\n// Keep the component reachable even though the default is null.\nvoid SearchKnowledgeBaseRenderer;\n","\"use client\";\n\n/**\n * ToolRenderer — the main dispatcher for tool invocations in the chat stream.\n *\n * Resolution order:\n * 1. `slots.tools[toolName]` — per-tool-name slot override\n * 2. `slots.toolRenderers[result.uiRenderMode]` — per-render-mode slot override\n * 3. `BUILTIN_NAMED_RENDERERS[toolName]` — special named built-ins\n * 4. `BUILTIN_TOOL_RENDERERS[result.uiRenderMode]` — built-in mode dispatch\n * 5. Fallback — clean JSON preview inside a Card\n *\n * Heavy renderers (`VisualizationRenderer`, `JsonRenderResult`) are loaded\n * lazily via `React.lazy` + `Suspense` to keep the core bundle small.\n */\n\nimport {\n lazy,\n Suspense,\n useEffect,\n useMemo,\n type ComponentType,\n} from \"react\";\nimport { useSlots } from \"../providers/SlotsContext\";\nimport { Card } from \"../ui/card\";\nimport { Spinner } from \"../ui/spinner\";\nimport type {\n ComponentAction,\n ToolRendererProps,\n ToolResult,\n} from \"../core/types\";\n// ToolRenderer may be rendered outside a ChatContext (e.g. standalone\n// previews), so we read the context defensively via a safe hook.\nimport { useSafeChatCallbacks, useSafeChatConfig } from \"./useSafeChatCallbacks\";\nimport {\n BUILTIN_NAMED_RENDERERS,\n BUILTIN_TOOL_RENDERERS,\n} from \"./tool-registry\";\nimport { ComponentRenderer } from \"./ComponentRenderer\";\n\n// ---------------------------------------------------------------------------\n// Lazy renderers\n// ---------------------------------------------------------------------------\n\nconst LazyVisualization = lazy(() =>\n import(\"./VisualizationRenderer\").then((m) => ({\n default: m.VisualizationRenderer,\n }))\n);\n\nconst LazyJsonRender = lazy(() =>\n import(\"../json-render/JsonRenderResult\").then((m) => ({\n default: m.JsonRenderResult as unknown as ComponentType<Record<string, unknown>>,\n }))\n);\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Return the best display payload for a tool result, preferring `_displayData`\n * (which the server strips before sending back to the LLM) over `data`.\n */\nfunction getDisplayData(result: ToolResult | undefined): unknown {\n if (!result) return undefined;\n if (result._displayData !== undefined) return result._displayData;\n return result.data;\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Default (fallback) renderers\n// ---------------------------------------------------------------------------\n\nfunction LoadingFallback({ text }: { text?: string }) {\n return (\n <div className=\"flex items-center gap-2 text-sm text-muted-foreground\">\n <Spinner className=\"h-4 w-4\" />\n <span>{text || \"Working...\"}</span>\n </div>\n );\n}\n\nfunction PresetPreview(props: ToolRendererProps) {\n const payload = getDisplayData(props.result);\n if (payload === undefined || payload === null) return null;\n return (\n <Card className=\"p-3\">\n <pre className=\"text-xs overflow-x-auto whitespace-pre-wrap break-words\">\n {safeStringify(payload)}\n </pre>\n </Card>\n );\n}\n\nfunction VisualizationWrapper(props: ToolRendererProps) {\n const payload = getDisplayData(props.result);\n // Accept either a full spec or `{ spec: ... }`.\n const spec =\n payload && typeof payload === \"object\" && \"type\" in (payload as object)\n ? (payload as Record<string, unknown>)\n : (payload as { spec?: Record<string, unknown> })?.spec;\n if (!spec) return null;\n return (\n <Suspense fallback={<LoadingFallback text={props.result?.loadingText} />}>\n {/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}\n <LazyVisualization spec={spec as any} />\n </Suspense>\n );\n}\n\nfunction JsonRenderWrapper(props: ToolRendererProps) {\n const spec = props.result?.jsonRenderSpec;\n const payload = getDisplayData(props.result);\n // Pull apiKey from the chat config so `call_api` actions in the spec\n // (e.g. form-submit buttons hitting /api/kb/form-submit) can attach the\n // project's Bearer token. Without this, third-party-domain embeds hit\n // 401 on submit — the matching headline bug.\n const chatConfig = useSafeChatConfig();\n if (!spec) return null;\n return (\n <Suspense fallback={<LoadingFallback text={props.result?.loadingText} />}>\n <LazyJsonRender\n spec={spec}\n data={payload}\n onSendMessage={props.onSendMessage}\n onAction={props.onAction}\n apiKey={chatConfig?.apiKey}\n apiEndpoint={chatConfig?.apiEndpoint}\n />\n </Suspense>\n );\n}\n\nfunction LegacyWrapper(props: ToolRendererProps) {\n const result = props.result;\n const payload = getDisplayData(result);\n const config = result?.customComponent;\n // `customComponent` in core/types is declared as `string`, but when used by\n // the legacy render mode the server inlines the `{ htmlCode, cssCode, ... }`\n // object. Widen the type locally.\n const cfg =\n typeof config === \"object\" && config !== null\n ? (config as {\n htmlCode?: string;\n cssCode?: string;\n mobileGridCols?: number;\n desktopGridCols?: number;\n mobilePageSize?: number;\n desktopPageSize?: number;\n })\n : null;\n if (!cfg?.htmlCode) return null;\n\n return (\n <ComponentRenderer\n htmlCode={cfg.htmlCode}\n cssCode={cfg.cssCode || \"\"}\n data={payload}\n mobileGridCols={cfg.mobileGridCols}\n desktopGridCols={cfg.desktopGridCols}\n mobilePageSize={cfg.mobilePageSize}\n desktopPageSize={cfg.desktopPageSize}\n />\n );\n}\n\nfunction FallbackPreview(props: ToolRendererProps) {\n const payload = getDisplayData(props.result);\n if (payload === undefined) return null;\n return (\n <Card className=\"p-3 bg-muted/30\">\n <pre className=\"text-xs overflow-x-auto whitespace-pre-wrap break-words\">\n {safeStringify(payload)}\n </pre>\n </Card>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Router\n// ---------------------------------------------------------------------------\n\n/**\n * Main tool renderer. Place one of these per tool invocation inside the\n * assistant message stream.\n */\ninterface PublicSlotMap {\n loader?: ComponentType<{ text?: string }>;\n tools?: Record<string, ComponentType<ToolRendererProps>>;\n toolRenderers?: Record<string, ComponentType<ToolRendererProps>>;\n}\n\n// Known render modes — used to detect tool-name typos in slots.toolRenderers.\nconst KNOWN_RENDER_MODES = new Set([\n \"visualization\",\n \"json_render\",\n \"json\",\n \"legacy\",\n \"display\",\n \"preset\",\n \"text\",\n \"none\",\n \"hidden\",\n]);\n\n// Track tool names we've already warned about to avoid log spam.\nconst warnedToolNames = new Set<string>();\n\nexport function ToolRenderer(props: ToolRendererProps) {\n const { toolName, state, result } = props;\n const slots = useSlots() as unknown as PublicSlotMap;\n const callbacks = useSafeChatCallbacks();\n\n // ----- Fire analytics callbacks -----\n useEffect(() => {\n if (state === \"output-available\" && result) {\n (callbacks as { onToolResult?: (...args: unknown[]) => void } | undefined)?.onToolResult?.(toolName, result, result.uiRenderMode);\n }\n }, [state, toolName, result, callbacks]);\n\n // ----- Dev warning: did the caller confuse `tools` and `toolRenderers`? -----\n // `toolRenderers` is keyed by render MODE. If a key looks like a tool name\n // (not a known mode) AND there's a tool result with that name, it's almost\n // certainly a mistake — the override will never fire.\n useEffect(() => {\n if (process.env.NODE_ENV === \"production\") return;\n const modeKeys = Object.keys(slots.toolRenderers || {});\n for (const key of modeKeys) {\n if (!KNOWN_RENDER_MODES.has(key) && key === toolName && !warnedToolNames.has(key)) {\n warnedToolNames.add(key);\n console.warn(\n `[aigentyc-chat-sdk] slots.toolRenderers[\"${key}\"] looks like a tool name, ` +\n `but toolRenderers is keyed by render MODE (visualization | json_render | ` +\n `legacy | preset | text). Did you mean slots.tools[\"${key}\"]?`,\n );\n }\n }\n }, [slots.toolRenderers, toolName]);\n\n // Wrap onAction to also forward to callbacks.onToolAction.\n const onAction = useMemo(() => {\n const userOnAction = props.onAction;\n return (action: ComponentAction, itemData?: unknown) => {\n (callbacks as { onToolAction?: (...args: unknown[]) => void } | undefined)?.onToolAction?.(action, itemData);\n userOnAction?.(action);\n };\n }, [callbacks, props.onAction]);\n\n // Build a prop-forwarding wrapper that swaps `onAction`.\n const forwardedProps: ToolRendererProps = { ...props, onAction };\n\n // ----- Pending / in-flight states -----\n if (state === \"partial-call\" || state === \"call\") {\n const slotLoader = (slots as { loader?: ComponentType<unknown> }).loader;\n if (slotLoader) {\n const L = slotLoader as ComponentType<{ text?: string }>;\n return <L text={result?.loadingText} />;\n }\n return <LoadingFallback text={result?.loadingText} />;\n }\n\n // Output-available — nothing to show if the result explicitly hides itself\n const mode = (result?.uiRenderMode as string | undefined) ?? \"preset\";\n if (mode === \"none\" || mode === \"hidden\") {\n // Still check named overrides in case a host wants to render a\n // side-effect-y tool.\n const named = slots.tools?.[toolName];\n if (named) {\n return renderWithDefault(named, forwardedProps, FallbackPreview);\n }\n return null;\n }\n\n // 1. per-tool slot override\n const toolSlot = slots.tools?.[toolName];\n if (toolSlot) {\n return renderWithDefault(toolSlot, forwardedProps, pickDefaultForMode(mode));\n }\n\n // 2. per-render-mode slot override\n const modeSlot = slots.toolRenderers?.[mode];\n if (modeSlot) {\n return renderWithDefault(modeSlot, forwardedProps, pickDefaultForMode(mode));\n }\n\n // 3. named built-in\n const namedBuiltin = BUILTIN_NAMED_RENDERERS[toolName];\n if (namedBuiltin === null && toolName in BUILTIN_NAMED_RENDERERS) {\n // explicit \"render nothing\" for this tool\n return null;\n }\n if (namedBuiltin) {\n const N = namedBuiltin;\n return <N {...forwardedProps} />;\n }\n\n // 4. built-in by render mode\n switch (mode) {\n case \"visualization\":\n return <VisualizationWrapper {...forwardedProps} />;\n case \"json_render\":\n case \"json\":\n return <JsonRenderWrapper {...forwardedProps} />;\n case \"legacy\":\n case \"display\":\n return <LegacyWrapper {...forwardedProps} />;\n case \"preset\":\n case \"text\":\n return <PresetPreview {...forwardedProps} />;\n default:\n // 5. fallback JSON card\n return <FallbackPreview {...forwardedProps} />;\n }\n}\n\nexport default ToolRenderer;\n\n// ---------------------------------------------------------------------------\n// Internals\n// ---------------------------------------------------------------------------\n\n/**\n * Render a slot override and inject the matching `DefaultComponent` so the\n * override can fall back to the built-in rendering.\n */\nfunction renderWithDefault(\n Override: ComponentType<ToolRendererProps & { DefaultComponent?: ComponentType<ToolRendererProps> }>,\n props: ToolRendererProps,\n Default: ComponentType<ToolRendererProps>\n) {\n return <Override {...props} DefaultComponent={Default} />;\n}\n\nfunction pickDefaultForMode(mode: string): ComponentType<ToolRendererProps> {\n switch (mode) {\n case \"visualization\":\n return VisualizationWrapper;\n case \"json_render\":\n case \"json\":\n return JsonRenderWrapper;\n case \"legacy\":\n case \"display\":\n return LegacyWrapper;\n case \"preset\":\n case \"text\":\n return PresetPreview;\n default:\n return FallbackPreview;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Re-exports for convenience\n// ---------------------------------------------------------------------------\n\nexport type { ToolRendererProps, ToolResult, ComponentAction };\n"]}
@@ -3,8 +3,8 @@ import { useAutoResize, useIsMobile, useLiveChat, usePreviewEmbed } from './chun
3
3
  import { useTheme } from './chunk-VQPOUMBC.js';
4
4
  import { Conversation, anchorToLatestTurn, FollowLatestTurn, ConversationContent, ConversationEmptyState, MessageAttachments, MessageAttachment, Sources, SourcesTrigger, SourcesContent, Source, MessageFeedback, LATEST_TURN_ATTR, Loader } from './chunk-TXX2W7ZR.js';
5
5
  import { useI18n } from './chunk-LDQVDUUJ.js';
6
- import { ToolRenderer } from './chunk-ZPOCKCBF.js';
7
- import { useChatContext, useSlots, renderSlot } from './chunk-G63CLUHC.js';
6
+ import { ToolRenderer } from './chunk-4DC55YI3.js';
7
+ import { useChatContext, useSlots, renderSlot } from './chunk-2HJZDMY2.js';
8
8
  import { cn } from './chunk-3RW7O444.js';
9
9
  import { memo, useState, useRef, useEffect, useCallback, Component, useMemo } from 'react';
10
10
  import { X, ArrowLeft, ShoppingCart, Plus, Ticket, FerrisWheel, Flag, Building, Heart, Star, Calendar, MapPin, Hotel, Coffee, Utensils, Settings, Users, FileText, HelpCircle, Search, Zap, MessageSquare, Shield, Minus, Trash2, Headset, Send, ThumbsUp, ThumbsDown, ExternalLink, SparklesIcon } from 'lucide-react';
@@ -1932,5 +1932,5 @@ function PreviewEmbedPanel({ isOpen, isRightSide, zIndex, panelWidth }) {
1932
1932
  }
1933
1933
 
1934
1934
  export { CartDrawer, ChatError, ChatErrorBoundary, ChatFooter, ChatHeader, ChatInput, ChatInterface, DEFAULT_PANEL_WIDTH, FloatingButton, LiveChatPanel, MobileLiveChatDrawer, PreviewEmbedPanel, QuickQuestions, SystemMessage, WelcomePage, panelMaxWidth };
1935
- //# sourceMappingURL=chunk-7TMQBROA.js.map
1936
- //# sourceMappingURL=chunk-7TMQBROA.js.map
1935
+ //# sourceMappingURL=chunk-7N5ELRVH.js.map
1936
+ //# sourceMappingURL=chunk-7N5ELRVH.js.map