@devicai/ui 0.47.0 → 0.49.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 (66) hide show
  1. package/dist/cjs/api/client.js +68 -4
  2. package/dist/cjs/api/client.js.map +1 -1
  3. package/dist/cjs/api/types.js.map +1 -1
  4. package/dist/cjs/components/AICommandBar/useAICommandBar.js +2 -2
  5. package/dist/cjs/components/AICommandBar/useAICommandBar.js.map +1 -1
  6. package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js +2 -2
  7. package/dist/cjs/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
  8. package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js +2 -2
  9. package/dist/cjs/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
  10. package/dist/cjs/components/ChatDrawer/ChatDrawer.js +8 -1
  11. package/dist/cjs/components/ChatDrawer/ChatDrawer.js.map +1 -1
  12. package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js +2 -1
  13. package/dist/cjs/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
  14. package/dist/cjs/components/IntegrationsModal/IntegrationsModal.js +36 -5
  15. package/dist/cjs/components/IntegrationsModal/IntegrationsModal.js.map +1 -1
  16. package/dist/cjs/components/IntegrationsModal/McpConnectForm.js +79 -0
  17. package/dist/cjs/components/IntegrationsModal/McpConnectForm.js.map +1 -0
  18. package/dist/cjs/components/IntegrationsModal/McpServersSection.js +234 -0
  19. package/dist/cjs/components/IntegrationsModal/McpServersSection.js.map +1 -0
  20. package/dist/cjs/components/IntegrationsModal/useTenantMcp.js +107 -0
  21. package/dist/cjs/components/IntegrationsModal/useTenantMcp.js.map +1 -0
  22. package/dist/cjs/hooks/useDevicChat.js +6 -7
  23. package/dist/cjs/hooks/useDevicChat.js.map +1 -1
  24. package/dist/cjs/index.js +6 -0
  25. package/dist/cjs/index.js.map +1 -1
  26. package/dist/cjs/styles.css +1 -1
  27. package/dist/cjs/utils/avatar.js +60 -0
  28. package/dist/cjs/utils/avatar.js.map +1 -0
  29. package/dist/esm/api/client.d.ts +48 -3
  30. package/dist/esm/api/client.js +68 -4
  31. package/dist/esm/api/client.js.map +1 -1
  32. package/dist/esm/api/types.d.ts +93 -0
  33. package/dist/esm/api/types.js.map +1 -1
  34. package/dist/esm/components/AICommandBar/useAICommandBar.js +2 -2
  35. package/dist/esm/components/AICommandBar/useAICommandBar.js.map +1 -1
  36. package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js +2 -2
  37. package/dist/esm/components/AIElementWrapper/useAIElementWrapper.js.map +1 -1
  38. package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js +2 -2
  39. package/dist/esm/components/AIGenerationButton/useAIGenerationButton.js.map +1 -1
  40. package/dist/esm/components/ChatDrawer/ChatDrawer.js +8 -1
  41. package/dist/esm/components/ChatDrawer/ChatDrawer.js.map +1 -1
  42. package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js +2 -1
  43. package/dist/esm/components/ChatDrawer/HandoffSubagentWidget.js.map +1 -1
  44. package/dist/esm/components/IntegrationsModal/IntegrationsModal.d.ts +8 -1
  45. package/dist/esm/components/IntegrationsModal/IntegrationsModal.js +36 -5
  46. package/dist/esm/components/IntegrationsModal/IntegrationsModal.js.map +1 -1
  47. package/dist/esm/components/IntegrationsModal/McpConnectForm.d.ts +42 -0
  48. package/dist/esm/components/IntegrationsModal/McpConnectForm.js +77 -0
  49. package/dist/esm/components/IntegrationsModal/McpConnectForm.js.map +1 -0
  50. package/dist/esm/components/IntegrationsModal/McpServersSection.d.ts +25 -0
  51. package/dist/esm/components/IntegrationsModal/McpServersSection.js +232 -0
  52. package/dist/esm/components/IntegrationsModal/McpServersSection.js.map +1 -0
  53. package/dist/esm/components/IntegrationsModal/index.d.ts +6 -0
  54. package/dist/esm/components/IntegrationsModal/useTenantMcp.d.ts +40 -0
  55. package/dist/esm/components/IntegrationsModal/useTenantMcp.js +105 -0
  56. package/dist/esm/components/IntegrationsModal/useTenantMcp.js.map +1 -0
  57. package/dist/esm/hooks/useDevicChat.js +6 -7
  58. package/dist/esm/hooks/useDevicChat.js.map +1 -1
  59. package/dist/esm/index.d.ts +3 -3
  60. package/dist/esm/index.js +3 -0
  61. package/dist/esm/index.js.map +1 -1
  62. package/dist/esm/styles.css +1 -1
  63. package/dist/esm/utils/avatar.d.ts +18 -0
  64. package/dist/esm/utils/avatar.js +58 -0
  65. package/dist/esm/utils/avatar.js.map +1 -0
  66. package/package.json +2 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"McpServersSection.js","sources":["../../../../../src/components/IntegrationsModal/McpServersSection.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState, type JSX } from \"react\";\nimport type {\n TenantMcpAuthInput,\n TenantMcpConnectResult,\n TenantMcpServer,\n} from \"../../api/types\";\nimport type { DevicTheme } from \"../theme\";\nimport { McpConnectForm } from \"./McpConnectForm\";\nimport type { TenantMcpState } from \"./useTenantMcp\";\n\nexport interface McpServersSectionProps {\n state: TenantMcpState;\n theme?: DevicTheme;\n /** Filter typed in the modal's search box. */\n query?: string;\n}\n\n/** Message the OAuth callback page posts back when an MCP connection is done. */\ninterface McpCallbackMessage {\n source?: string;\n type?: string;\n status?: string;\n returnTo?: string;\n}\n\n/** A random value tying an OAuth round trip to the window that started it. */\nfunction newNonce(): string {\n const c = typeof crypto !== \"undefined\" ? crypto : undefined;\n if (c?.randomUUID) return c.randomUUID();\n return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\n}\n\nfunction stateOf(server: TenantMcpServer): {\n key: \"connected\" | \"reconnect\" | \"disconnected\";\n label: string;\n} {\n const status = server.connection?.status;\n if (status === \"active\") return { key: \"connected\", label: \"Connected\" };\n if (status === \"error\") return { key: \"reconnect\", label: \"Needs attention\" };\n if (status === \"pending_auth\")\n return { key: \"reconnect\", label: \"Waiting for sign-in\" };\n return { key: \"disconnected\", label: \"Not connected\" };\n}\n\nfunction matches(server: TenantMcpServer, query: string): boolean {\n const q = query.trim().toLowerCase();\n if (!q) return true;\n return (\n server.name.toLowerCase().includes(q) ||\n server.url.toLowerCase().includes(q) ||\n (server.description ?? \"\").toLowerCase().includes(q)\n );\n}\n\n/** Identity of a row, stable whether or not it has been connected yet. */\nfunction keyOf(server: TenantMcpServer): string {\n return server.connection?.id ?? server.templateId ?? server.url;\n}\n\n/**\n * The MCP servers section of the connected-apps panel.\n *\n * The end user sees one list: the servers their developer left ready to\n * connect, the ones they added themselves, and — unless it was switched off —\n * a button to add another. Both routes open the same form, because the only\n * difference between them is who typed the url.\n *\n * Connecting opens a consent screen in a popup. The popup is opened empty\n * *before* the request that produces its URL, because browsers only honour\n * `window.open` inside the gesture that triggered it; opening it after the\n * round trip is what gets it blocked. Two endings are watched, not one — a\n * cancelled consent screen posts nothing back, so the close is watched too.\n */\nexport function McpServersSection({\n state,\n theme,\n query = \"\",\n}: McpServersSectionProps): JSX.Element | null {\n const { servers, allowCustom, limits, loading, client, scope, refresh } = state;\n\n const [actionError, setActionError] = useState<string | null>(null);\n const [busyKey, setBusyKey] = useState<string | null>(null);\n const [blockedUrl, setBlockedUrl] = useState<{ url: string } | null>(null);\n /** The row whose form is open. `null` inside the object is \"add your own\". */\n const [prompt, setPrompt] = useState<{\n server: TenantMcpServer | null;\n callbackUrl?: string;\n needsClientCredentials?: boolean;\n } | null>(null);\n const [formError, setFormError] = useState<string | null>(null);\n\n const pendingRef = useRef<{ returnTo: string } | null>(null);\n const popupRef = useRef<Window | null>(null);\n const pollRef = useRef<number | null>(null);\n\n const finish = useCallback(() => {\n if (pollRef.current !== null) {\n window.clearInterval(pollRef.current);\n pollRef.current = null;\n }\n pendingRef.current = null;\n popupRef.current = null;\n setBusyKey(null);\n void refresh();\n }, [refresh]);\n\n // The callback page says it is done. A nudge, never the result: what is shown\n // comes from re-reading the server, so a forged message costs one extra fetch\n // and nothing else.\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n const data = event.data as McpCallbackMessage | undefined;\n if (!data || data.source !== \"devic\") return;\n if (data.type !== \"mcp-connected\") return;\n const pending = pendingRef.current;\n if (!pending || data.returnTo !== pending.returnTo) return;\n popupRef.current?.close();\n finish();\n };\n window.addEventListener(\"message\", onMessage);\n return () => window.removeEventListener(\"message\", onMessage);\n }, [finish]);\n\n useEffect(\n () => () => {\n if (pollRef.current !== null) window.clearInterval(pollRef.current);\n },\n []\n );\n\n const openPrompt = (server: TenantMcpServer | null) => {\n setFormError(null);\n setActionError(null);\n setBlockedUrl(null);\n setPrompt({ server });\n };\n\n const submit = async (values: {\n url?: string;\n name?: string;\n auth: TenantMcpAuthInput;\n }) => {\n if (!client || !prompt) return;\n const server = prompt.server;\n const rowKey = server ? keyOf(server) : \"new\";\n setBusyKey(rowKey);\n setFormError(null);\n\n const nonce = newNonce();\n const returnTo = `${window.location.origin}/?devic_mcp=${nonce}`;\n // Opened empty inside the submit gesture and navigated once the URL is\n // known. Skipped when no browser is involved at all.\n const popup =\n values.auth.mode === \"oauth\"\n ? window.open(\n \"\",\n \"devic-mcp-oauth\",\n \"width=520,height=680,menubar=no,toolbar=no\"\n )\n : null;\n\n try {\n const existing = server?.connection;\n const result: TenantMcpConnectResult = existing\n ? await client.reconnectMcpServer(existing.id, {\n ...scope,\n returnTo,\n auth: values.auth,\n })\n : await client.connectMcpServer({\n ...scope,\n returnTo,\n templateId: server?.templateId,\n url: values.url,\n name: values.name,\n auth: values.auth,\n });\n\n if (result.requiresClientCredentials) {\n // Not a failure the user can do nothing about: they own the server, so\n // the form reopens with the fields and the redirect URI to authorise.\n popup?.close();\n setBusyKey(null);\n setPrompt({\n server,\n callbackUrl: result.callbackUrl,\n needsClientCredentials: true,\n });\n setFormError(result.error ?? null);\n return;\n }\n\n if (result.status === \"error\") {\n popup?.close();\n setBusyKey(null);\n setFormError(result.error ?? \"The server could not be reached.\");\n return;\n }\n\n if (!result.authorizationUrl) {\n // Connected outright: the key the user typed is the credential.\n popup?.close();\n setPrompt(null);\n finish();\n return;\n }\n\n pendingRef.current = { returnTo };\n setPrompt(null);\n if (popup && !popup.closed) {\n popupRef.current = popup;\n popup.location.href = result.authorizationUrl;\n pollRef.current = window.setInterval(() => {\n if (popup.closed) finish();\n }, 700);\n } else {\n // Blocked (Safari, in-app browsers, extensions): hand over the URL.\n setBlockedUrl({ url: result.authorizationUrl });\n setBusyKey(null);\n }\n } catch (err) {\n popup?.close();\n pendingRef.current = null;\n setBusyKey(null);\n setFormError(err instanceof Error ? err.message : String(err));\n }\n };\n\n const disconnect = async (server: TenantMcpServer) => {\n const connection = server.connection;\n if (!client || !connection || busyKey) return;\n setBusyKey(keyOf(server));\n setActionError(null);\n try {\n await client.disconnectMcpServer(connection.id, scope);\n await refresh();\n } catch (err) {\n setActionError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusyKey(null);\n }\n };\n\n const visible = servers.filter((s) => matches(s, query));\n const atLimit = limits.used >= limits.maxServers;\n\n // Nothing offered and nothing addable: the whole section would be a heading\n // over an empty box, which says less than saying nothing.\n if (!servers.length && !allowCustom) return null;\n\n return (\n <div className=\"devic-int-mcp-section\">\n <div className=\"devic-int-mcp-heading\">\n <h4>MCP servers</h4>\n <span>Connect a server and its tools become available in this chat.</span>\n </div>\n\n {actionError && <div className=\"devic-int-error\">{actionError}</div>}\n\n {blockedUrl && (\n <div className=\"devic-int-notice\">\n Your browser blocked the pop-up.{\" \"}\n <a\n href={blockedUrl.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={() => {\n pendingRef.current = null;\n setBlockedUrl(null);\n }}\n >\n Open the authorisation page\n </a>{\" \"}\n and come back — then use Refresh.\n </div>\n )}\n\n {visible.length > 0 && (\n <div className=\"devic-int-grid\">\n {visible.map((server) => {\n const cardState = stateOf(server);\n const rowKey = keyOf(server);\n const busy = busyKey === rowKey;\n const connection = server.connection;\n return (\n <div\n key={rowKey}\n className=\"devic-int-card\"\n data-state={cardState.key}\n >\n <div className=\"devic-int-card-head\">\n {server.logoUrl ? (\n <img\n className=\"devic-int-mcp-logo\"\n src={server.logoUrl}\n alt=\"\"\n aria-hidden=\"true\"\n />\n ) : (\n <span className=\"devic-int-mcp-logo devic-int-mcp-logo-fallback\">\n {server.name.slice(0, 1).toUpperCase()}\n </span>\n )}\n <span className=\"devic-int-state\">\n <span\n className=\"devic-int-dot\"\n data-ok={cardState.key === \"connected\"}\n data-off={cardState.key === \"disconnected\"}\n aria-hidden=\"true\"\n />\n {cardState.label}\n </span>\n </div>\n\n <div className=\"devic-int-name\" title={server.name}>\n {server.name}\n </div>\n\n <div\n className=\"devic-int-description\"\n title={server.description ?? server.url}\n >\n {server.description ?? server.url}\n </div>\n\n {connection?.shared && (\n // Worth saying before they wonder why they cannot remove it.\n <div className=\"devic-int-mcp-note\">\n Connected for everyone on this account\n </div>\n )}\n\n {connection?.status === \"active\" &&\n typeof connection.toolCount === \"number\" && (\n <div className=\"devic-int-mcp-note\">\n {connection.toolCount} tool\n {connection.toolCount === 1 ? \"\" : \"s\"} available\n </div>\n )}\n\n {connection?.lastProbeError && (\n <div\n className=\"devic-int-mcp-note devic-int-mcp-note-warn\"\n title={connection.lastProbeError}\n >\n {connection.lastProbeError}\n </div>\n )}\n\n <button\n type=\"button\"\n className={`devic-int-btn devic-int-btn-block${\n cardState.key === \"connected\" ? \"\" : \" devic-int-btn-primary\"\n }`}\n onClick={() => openPrompt(server)}\n disabled={\n busy ||\n !!busyKey ||\n connection?.readOnly ||\n (!connection && atLimit)\n }\n title={\n connection?.readOnly\n ? \"This server was connected for the whole account.\"\n : !connection && atLimit\n ? `You can have ${limits.maxServers} connected at a time.`\n : undefined\n }\n >\n {busy\n ? \"Waiting…\"\n : cardState.key === \"disconnected\"\n ? \"Connect\"\n : \"Reconnect\"}\n </button>\n\n {connection && !connection.readOnly && (\n <button\n type=\"button\"\n className=\"devic-int-btn devic-int-btn-block devic-int-mcp-remove\"\n onClick={() => void disconnect(server)}\n disabled={!!busyKey}\n >\n Disconnect\n </button>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {allowCustom && (\n <button\n type=\"button\"\n className=\"devic-int-btn devic-int-mcp-add\"\n onClick={() => openPrompt(null)}\n disabled={loading || !!busyKey || atLimit}\n title={\n atLimit\n ? `You can have ${limits.maxServers} MCP server${\n limits.maxServers === 1 ? \"\" : \"s\"\n } connected at a time.`\n : undefined\n }\n >\n + Add your own MCP\n </button>\n )}\n\n {prompt && (\n <McpConnectForm\n server={prompt.server}\n callbackUrl={prompt.callbackUrl}\n needsClientCredentials={prompt.needsClientCredentials}\n submitting={\n busyKey === (prompt.server ? keyOf(prompt.server) : \"new\")\n }\n error={formError}\n theme={theme}\n onCancel={() => {\n setPrompt(null);\n setFormError(null);\n }}\n onSubmit={submit}\n />\n )}\n </div>\n );\n}\n\nexport default McpServersSection;\n"],"names":["useState","useRef","useCallback","useEffect","_jsxs","_jsx","McpConnectForm"],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+ var client = require('../../api/client.js');
5
+ require('react/jsx-runtime');
6
+ var DevicContext = require('../../provider/DevicContext.js');
7
+
8
+ /** A 4xx here means "not for you", not "something broke". */
9
+ function isRefusal(err) {
10
+ const status = err?.statusCode;
11
+ return typeof status === "number" && status >= 400 && status < 500;
12
+ }
13
+ const NO_LIMITS = { maxServers: 0, maxToolsPerServer: 0, used: 0 };
14
+ /**
15
+ * The MCP servers an assistant offers its tenants, together with the ones this
16
+ * tenant has connected — loaded once and shared.
17
+ *
18
+ * Deliberately a sibling of `useIntegrations` rather than part of it: the two
19
+ * answer different endpoints, and folding them together would mean an assistant
20
+ * that offers only one of them pays for both on every open.
21
+ */
22
+ function useTenantMcp(options) {
23
+ const { assistantId, tenantId, subtenantId, apiKey, baseUrl, enabled = true } = options;
24
+ const context = DevicContext.useOptionalDevicContext();
25
+ const resolvedBaseUrl = baseUrl || context?.baseUrl || "https://api.devic.ai";
26
+ const resolvedTenantId = tenantId || context?.tenantId;
27
+ const resolvedSubtenantId = subtenantId || context?.subtenantId;
28
+ const resolvedApiKey = apiKey || context?.apiKey;
29
+ const resolvedTenantSession = context?.getTenantSession;
30
+ const onSessionExpired = context?.onSessionExpired;
31
+ const client$1 = React.useMemo(() => resolvedApiKey || resolvedTenantSession
32
+ ? new client.DevicApiClient({
33
+ apiKey: resolvedApiKey,
34
+ baseUrl: resolvedBaseUrl,
35
+ getTenantSession: resolvedTenantSession,
36
+ onSessionExpired,
37
+ })
38
+ : null, [resolvedApiKey, resolvedTenantSession, resolvedBaseUrl]);
39
+ const scope = React.useMemo(() => ({
40
+ assistantId,
41
+ tenantId: resolvedTenantId || undefined,
42
+ subtenantId: resolvedSubtenantId || undefined,
43
+ }), [assistantId, resolvedTenantId, resolvedSubtenantId]);
44
+ const [listing, setListing] = React.useState(null);
45
+ const [loading, setLoading] = React.useState(false);
46
+ const [error, setError] = React.useState(null);
47
+ const [settled, setSettled] = React.useState(false);
48
+ const refresh = React.useCallback(async () => {
49
+ if (!client$1) {
50
+ setError("No credentials configured");
51
+ setSettled(true);
52
+ return;
53
+ }
54
+ setLoading(true);
55
+ setError(null);
56
+ try {
57
+ setListing(await client$1.getMcpServers(scope));
58
+ }
59
+ catch (err) {
60
+ setListing(null);
61
+ setError(err instanceof Error ? err.message : String(err));
62
+ if (!isRefusal(err)) {
63
+ // A refusal is an ordinary answer — a disabled feature, a missing
64
+ // tenant — and stays quiet. A 500 is not, and swallowing it would
65
+ // leave an integrator with a panel that never appears and no reason.
66
+ console.warn("[devic-ui] could not load MCP servers", err);
67
+ }
68
+ }
69
+ finally {
70
+ setLoading(false);
71
+ setSettled(true);
72
+ }
73
+ }, [client$1, scope]);
74
+ // Once per scope, not once per render of whatever switched it on. A different
75
+ // tenant is a different listing, and the previous one is dropped first:
76
+ // showing it while the new one arrives would name servers that are not this
77
+ // user's.
78
+ const key = `${client$1 ? "k" : "-"}|${scope.assistantId}|${scope.tenantId ?? ""}|${scope.subtenantId ?? ""}`;
79
+ const loadedKeyRef = React.useRef(null);
80
+ React.useEffect(() => {
81
+ if (!enabled || loadedKeyRef.current === key)
82
+ return;
83
+ if (loadedKeyRef.current !== null) {
84
+ setListing(null);
85
+ setSettled(false);
86
+ }
87
+ loadedKeyRef.current = key;
88
+ void refresh();
89
+ }, [enabled, key, refresh]);
90
+ return {
91
+ servers: listing?.servers ?? [],
92
+ loading,
93
+ error,
94
+ // Offered only once the server has said so. Anything hanging off this stays
95
+ // hidden until then, so nothing appears and then disappears.
96
+ offered: !!listing?.offered,
97
+ allowCustom: !!listing?.allowCustom,
98
+ limits: listing?.limits ?? NO_LIMITS,
99
+ settled,
100
+ refresh,
101
+ client: client$1,
102
+ scope,
103
+ };
104
+ }
105
+
106
+ exports.useTenantMcp = useTenantMcp;
107
+ //# sourceMappingURL=useTenantMcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTenantMcp.js","sources":["../../../../../src/components/IntegrationsModal/useTenantMcp.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { DevicApiError } from \"../../api/client\";\nimport { DevicApiClient } from \"../../api/client\";\nimport type { TenantMcpListing, TenantMcpServer } from \"../../api/types\";\nimport { useOptionalDevicContext } from \"../../provider\";\nimport type { IntegrationsScope } from \"./useIntegrations\";\n\nexport interface UseTenantMcpOptions extends IntegrationsScope {\n apiKey?: string;\n baseUrl?: string;\n /**\n * Fetch when this turns true, and only then. The modal passes its own open\n * state, so a panel nobody opens costs no request at all.\n */\n enabled?: boolean;\n}\n\nexport interface TenantMcpState {\n servers: TenantMcpServer[];\n loading: boolean;\n error: string | null;\n /** Whether this assistant offers MCP servers to its tenants at all. */\n offered: boolean;\n /** Whether the end user may add a server of their own. */\n allowCustom: boolean;\n limits: { maxServers: number; maxToolsPerServer: number; used: number };\n /** True once a first answer (or refusal) has arrived. */\n settled: boolean;\n refresh: () => Promise<void>;\n client: DevicApiClient | null;\n scope: IntegrationsScope;\n}\n\n/** A 4xx here means \"not for you\", not \"something broke\". */\nfunction isRefusal(err: unknown): boolean {\n const status = (err as DevicApiError)?.statusCode;\n return typeof status === \"number\" && status >= 400 && status < 500;\n}\n\nconst NO_LIMITS = { maxServers: 0, maxToolsPerServer: 0, used: 0 };\n\n/**\n * The MCP servers an assistant offers its tenants, together with the ones this\n * tenant has connected — loaded once and shared.\n *\n * Deliberately a sibling of `useIntegrations` rather than part of it: the two\n * answer different endpoints, and folding them together would mean an assistant\n * that offers only one of them pays for both on every open.\n */\nexport function useTenantMcp(options: UseTenantMcpOptions): TenantMcpState {\n const { assistantId, tenantId, subtenantId, apiKey, baseUrl, enabled = true } =\n options;\n\n const context = useOptionalDevicContext();\n const resolvedBaseUrl = baseUrl || context?.baseUrl || \"https://api.devic.ai\";\n const resolvedTenantId = tenantId || context?.tenantId;\n const resolvedSubtenantId = subtenantId || context?.subtenantId;\n const resolvedApiKey = apiKey || context?.apiKey;\n const resolvedTenantSession = context?.getTenantSession;\n const onSessionExpired = context?.onSessionExpired;\n\n const client = useMemo(\n () =>\n resolvedApiKey || resolvedTenantSession\n ? new DevicApiClient({\n apiKey: resolvedApiKey,\n baseUrl: resolvedBaseUrl,\n getTenantSession: resolvedTenantSession,\n onSessionExpired,\n })\n : null,\n [resolvedApiKey, resolvedTenantSession, resolvedBaseUrl]\n );\n\n const scope = useMemo(\n () => ({\n assistantId,\n tenantId: resolvedTenantId || undefined,\n subtenantId: resolvedSubtenantId || undefined,\n }),\n [assistantId, resolvedTenantId, resolvedSubtenantId]\n );\n\n const [listing, setListing] = useState<TenantMcpListing | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [settled, setSettled] = useState(false);\n\n const refresh = useCallback(async () => {\n if (!client) {\n setError(\"No credentials configured\");\n setSettled(true);\n return;\n }\n setLoading(true);\n setError(null);\n try {\n setListing(await client.getMcpServers(scope));\n } catch (err) {\n setListing(null);\n setError(err instanceof Error ? err.message : String(err));\n if (!isRefusal(err)) {\n // A refusal is an ordinary answer — a disabled feature, a missing\n // tenant — and stays quiet. A 500 is not, and swallowing it would\n // leave an integrator with a panel that never appears and no reason.\n console.warn(\"[devic-ui] could not load MCP servers\", err);\n }\n } finally {\n setLoading(false);\n setSettled(true);\n }\n }, [client, scope]);\n\n // Once per scope, not once per render of whatever switched it on. A different\n // tenant is a different listing, and the previous one is dropped first:\n // showing it while the new one arrives would name servers that are not this\n // user's.\n const key = `${client ? \"k\" : \"-\"}|${scope.assistantId}|${scope.tenantId ?? \"\"}|${scope.subtenantId ?? \"\"}`;\n const loadedKeyRef = useRef<string | null>(null);\n useEffect(() => {\n if (!enabled || loadedKeyRef.current === key) return;\n if (loadedKeyRef.current !== null) {\n setListing(null);\n setSettled(false);\n }\n loadedKeyRef.current = key;\n void refresh();\n }, [enabled, key, refresh]);\n\n return {\n servers: listing?.servers ?? [],\n loading,\n error,\n // Offered only once the server has said so. Anything hanging off this stays\n // hidden until then, so nothing appears and then disappears.\n offered: !!listing?.offered,\n allowCustom: !!listing?.allowCustom,\n limits: listing?.limits ?? NO_LIMITS,\n settled,\n refresh,\n client,\n scope,\n };\n}\n"],"names":["useOptionalDevicContext","client","useMemo","DevicApiClient","useState","useCallback","useRef","useEffect"],"mappings":"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"}
@@ -323,8 +323,9 @@ function useDevicChat(options) {
323
323
  setIsLoading(false);
324
324
  }
325
325
  if (responses.length > 0) {
326
- // Send tool responses back to the API
327
- await clientRef.current.sendToolResponses(assistantId, chatUid, responses);
326
+ // Send tool responses back to the API, restating the tools so the
327
+ // continuation keeps them on offer
328
+ await clientRef.current.sendToolResponses(assistantId, chatUid, responses, toolSchemas);
328
329
  // Only resume polling if no widgets are blocking
329
330
  if (widgetCalls.length === 0) {
330
331
  setShouldPoll(true);
@@ -337,7 +338,7 @@ function useDevicChat(options) {
337
338
  setError(error);
338
339
  onErrorRef.current?.(error);
339
340
  }
340
- }, [chatUid, assistantId, handleToolCalls, extractPendingToolCalls]);
341
+ }, [chatUid, assistantId, handleToolCalls, extractPendingToolCalls, toolSchemas]);
341
342
  // Send a message
342
343
  const sendMessage = React.useCallback(async (message, sendOptions) => {
343
344
  if (!clientRef.current) {
@@ -603,9 +604,7 @@ function useDevicChat(options) {
603
604
  setPendingWidgetCalls(remaining);
604
605
  try {
605
606
  logRef.current.log('[useDevicChat] sending widget tool response', toolCallId);
606
- await clientRef.current.sendToolResponses(assistantId, uid, [
607
- { tool_call_id: toolCallId, content: response, role: 'tool' },
608
- ]);
607
+ await clientRef.current.sendToolResponses(assistantId, uid, [{ tool_call_id: toolCallId, content: response, role: 'tool' }], toolSchemas);
609
608
  // Resume polling only if no more widget calls are blocking
610
609
  if (remaining.length === 0) {
611
610
  setShouldPoll(true);
@@ -618,7 +617,7 @@ function useDevicChat(options) {
618
617
  setError(error);
619
618
  onErrorRef.current?.(error);
620
619
  }
621
- }, [assistantId]);
620
+ }, [assistantId, toolSchemas]);
622
621
  // Cancel a pending widget tool call (sends an error response to the model)
623
622
  const cancelWidgetCall = React.useCallback(async (toolCallId, reason) => {
624
623
  await submitWidgetResponse(toolCallId, {
@@ -1 +1 @@
1
- {"version":3,"file":"useDevicChat.js","sources":["../../../../src/hooks/useDevicChat.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useOptionalDevicContext } from '../provider';\nimport type { TenantMetadata, SubtenantMetadata } from '../provider';\nimport { DevicApiClient, DevicApiError } from '../api/client';\nimport { usePolling, resolvePollingInterval } from './usePolling';\nimport { useModelInterface, type PendingWidgetCall } from './useModelInterface';\nimport { createLogger } from '../utils/logger';\nimport type {\n ChatMessage,\n ChatFile,\n ModelInterfaceTool,\n RealtimeChatHistory,\n RealtimeStatus,\n RecalledMemoryRecord,\n TenantLimitExceeded,\n} from '../api/types';\n\n/**\n * Cadence for the handoff watch, which only waits for the parent thread to\n * leave `handed_off` and so does not need the main conversation's rhythm.\n * A configured `pollingInterval` still wins over it.\n */\nconst DEFAULT_HANDOFF_POLL_INTERVAL_MS = 5000;\n\nexport interface UseDevicChatOptions {\n /**\n * Assistant identifier\n */\n assistantId: string;\n\n /**\n * Existing chat UID to continue a conversation\n */\n chatUid?: string;\n\n /**\n * API key (overrides provider context)\n */\n apiKey?: string;\n\n /**\n * Base URL (overrides provider context)\n */\n baseUrl?: string;\n\n /**\n * Tenant ID for multi-tenant environments\n */\n tenantId?: string;\n\n /**\n * Tenant metadata (e.g. { name, email, imageUrl })\n */\n tenantMetadata?: TenantMetadata;\n\n /**\n * Subtenant ID identifying a user/entity inside the tenant\n */\n subtenantId?: string;\n\n /**\n * Subtenant metadata (e.g. { id, name, email, imageUrl })\n */\n subtenantMetadata?: SubtenantMetadata;\n\n /**\n * Tags applied to the conversation. Sent as the top-level `tags` of each\n * message (distinct from metadata). Falls back to the DevicProvider's `tags`\n * and is merged (deduped) with any per-message tags passed to `sendMessage`.\n */\n tags?: string[];\n\n /**\n * Tools enabled from the assistant's configured tool groups\n */\n enabledTools?: string[];\n\n /**\n * Apps the end user connected that should sit out the messages sent from\n * here, by slug (`[\"gmail\"]`).\n *\n * A deny list over their own connected apps, not over the assistant's tools:\n * what is not named stays available. Sent with every message while it is set,\n * so it lasts as long as the caller keeps it set — the server keeps nothing\n * and the account is never disconnected.\n */\n disabledIntegrations?: string[];\n\n /**\n * Client-side tools for model interface protocol\n */\n modelInterfaceTools?: ModelInterfaceTool[];\n\n /**\n * How often (ms) the conversation in progress is polled for new content.\n * Overrides the DevicProvider's `pollingInterval`. Values below 250 ms are\n * clamped.\n * @default 1000\n */\n pollingInterval?: number;\n\n /**\n * Callback when a message is sent\n */\n onMessageSent?: (message: ChatMessage) => void;\n\n /**\n * Callback when a message is received\n */\n onMessageReceived?: (message: ChatMessage) => void;\n\n /**\n * Callback when a tool is called\n */\n onToolCall?: (toolName: string, params: any) => void;\n\n /**\n * Callback when an error occurs\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when a new chat is created\n */\n onChatCreated?: (chatUid: string) => void;\n\n /**\n * Custom file upload handler. When provided, replaces the default\n * upload to Devic API. Receives the raw File objects and must return\n * an array of ChatFile with downloadUrl set.\n */\n onFileUpload?: (files: File[]) => Promise<ChatFile[]>;\n\n /**\n * Enable debug logging to the browser console.\n * Overrides the provider-level debug setting when provided.\n * @default false\n */\n debug?: boolean;\n}\n\nexport interface UseDevicChatResult {\n /**\n * Current chat messages\n */\n messages: ChatMessage[];\n\n /**\n * Current chat UID\n */\n chatUid: string | null;\n\n /**\n * Whether a message is being processed\n */\n isLoading: boolean;\n\n /**\n * Current status\n */\n status: RealtimeStatus | 'idle';\n\n /**\n * Last error\n */\n error: Error | null;\n\n /**\n * Set when the last message was blocked by a tenant/subtenant usage limit\n * (HTTP 429 / realtime status `limit_exceeded`). Carries the blocking rule,\n * current vs. limit and when the window resets. `null` while not limited.\n * Cleared when a new message is sent or the chat is cleared.\n */\n limitExceeded: TenantLimitExceeded | null;\n\n /**\n * Structured long-term-memory recall events of the conversation, streamed\n * in while the assistant is still processing (via the realtime poll) and\n * hydrated from the persisted history on load. Empty for assistants\n * without memory.\n */\n recalledMemories: RecalledMemoryRecord[];\n\n /**\n * Whether the assistant has handed off to a subagent\n */\n handedOff: boolean;\n\n /**\n * The subthread ID when a handoff is active\n */\n handedOffSubThreadId: string | null;\n\n /**\n * Send a message\n */\n sendMessage: (\n message: string,\n options?: {\n files?: File[];\n metadata?: Record<string, any>;\n /** Id of a speech-to-text transcript that seeded this message. */\n transcriptId?: string;\n /** Per-message tags, merged (deduped) with the resolved conversation tags. */\n tags?: string[];\n /**\n * Connected apps to leave out of this one message, by slug. Replaces the\n * hook's own `disabledIntegrations` rather than adding to it, so a caller\n * can send one message with everything on by passing `[]`.\n */\n disabledIntegrations?: string[];\n }\n ) => Promise<void>;\n\n /**\n * Clear the chat and start a new conversation\n */\n clearChat: () => void;\n\n /**\n * Load an existing chat\n */\n loadChat: (chatUid: string) => Promise<void>;\n\n /**\n * Called when the handoff subagent completes.\n * Triggers reload of full chat content.\n */\n onHandoffCompleted: () => void;\n\n /**\n * Stop the current conversation processing (client-side only).\n * Stops polling and resets loading state.\n */\n stopChat: () => void;\n\n /**\n * Pending tool calls that require user interaction via a response widget\n */\n pendingWidgetCalls: PendingWidgetCall[];\n\n /**\n * Submit a response for a pending widget tool call.\n * Sends the response to the API and resumes the conversation.\n */\n submitWidgetResponse: (toolCallId: string, response: any) => Promise<void>;\n\n /**\n * Cancel a pending widget tool call.\n * Sends an error response so the model can continue.\n */\n cancelWidgetCall: (toolCallId: string, reason?: string) => Promise<void>;\n}\n\n/**\n * Main hook for managing chat with a Devic assistant\n *\n * @example\n * ```tsx\n * const {\n * messages,\n * isLoading,\n * sendMessage,\n * } = useDevicChat({\n * assistantId: 'my-assistant',\n * modelInterfaceTools: [\n * {\n * toolName: 'get_user_location',\n * schema: { ... },\n * callback: async () => ({ lat: 40.7, lng: -74.0 })\n * }\n * ],\n * onMessageReceived: (msg) => console.log('Received:', msg),\n * });\n * ```\n */\nexport function useDevicChat(options: UseDevicChatOptions): UseDevicChatResult {\n const {\n assistantId,\n chatUid: initialChatUid,\n apiKey: propsApiKey,\n baseUrl: propsBaseUrl,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n enabledTools,\n disabledIntegrations,\n modelInterfaceTools = [],\n pollingInterval: propsPollingInterval,\n onMessageSent,\n onMessageReceived,\n onToolCall,\n onError,\n onChatCreated,\n onFileUpload,\n debug: propsDebug,\n } = options;\n\n // Get context (may be null if not wrapped in provider)\n const context = useOptionalDevicContext();\n\n // Resolve configuration\n const apiKey = propsApiKey || context?.apiKey;\n const getTenantSession = context?.getTenantSession;\n const onSessionExpired = context?.onSessionExpired;\n const baseUrl = propsBaseUrl || context?.baseUrl || 'https://api.devic.ai';\n const resolvedTenantId = tenantId || context?.tenantId;\n const resolvedTenantMetadata = { ...context?.tenantMetadata, ...tenantMetadata };\n const resolvedSubtenantId = subtenantId || context?.subtenantId;\n const resolvedSubtenantMetadata = {\n ...context?.subtenantMetadata,\n ...subtenantMetadata,\n };\n // Provider tags + hook tags, deduped. Per-message tags are merged at send time.\n const resolvedTags = useMemo(\n () => Array.from(new Set([...(context?.tags ?? []), ...(tags ?? [])])),\n [context?.tags, tags]\n );\n const pollingInterval = resolvePollingInterval(\n propsPollingInterval,\n context?.pollingInterval\n );\n const handoffPollingInterval = resolvePollingInterval(\n propsPollingInterval,\n context?.pollingInterval,\n DEFAULT_HANDOFF_POLL_INTERVAL_MS\n );\n const debug = propsDebug ?? context?.debug ?? false;\n const log = useMemo(() => createLogger(debug), [debug]);\n const logRef = useRef(log);\n logRef.current = log;\n\n // State\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [chatUid, setChatUid] = useState<string | null>(initialChatUid || null);\n const [isLoading, setIsLoading] = useState(false);\n const [status, setStatus] = useState<RealtimeStatus | 'idle'>('idle');\n const [error, setError] = useState<Error | null>(null);\n const [limitExceeded, setLimitExceeded] = useState<TenantLimitExceeded | null>(\n null\n );\n\n // Long-term-memory recall events of the conversation. The realtime blob\n // only carries the in-flight run's records, so incoming batches merge (by\n // uid) instead of replacing — earlier runs' recalls stay visible.\n const [recalledMemories, setRecalledMemories] = useState<RecalledMemoryRecord[]>([]);\n const mergeRecalledMemories = useCallback(\n (incoming?: RecalledMemoryRecord[]) => {\n if (!incoming?.length) return;\n setRecalledMemories((prev) => {\n const known = new Set(prev.map((r) => r.uid));\n const fresh = incoming.filter((r) => !known.has(r.uid));\n return fresh.length ? [...prev, ...fresh] : prev;\n });\n },\n []\n );\n\n // Handoff state\n const [handedOff, setHandedOff] = useState(false);\n const [handedOffSubThreadId, setHandedOffSubThreadId] = useState<string | null>(null);\n const handoffPollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // Polling state\n const [shouldPoll, setShouldPoll] = useState(false);\n\n // Keep a ref to chatUid so async callbacks always read the latest value\n const chatUidRef = useRef(chatUid);\n chatUidRef.current = chatUid;\n\n // Refs for callbacks\n const onMessageReceivedRef = useRef(onMessageReceived);\n const onErrorRef = useRef(onError);\n const onChatCreatedRef = useRef(onChatCreated);\n\n useEffect(() => {\n onMessageReceivedRef.current = onMessageReceived;\n onErrorRef.current = onError;\n onChatCreatedRef.current = onChatCreated;\n });\n\n // Create API client\n const clientRef = useRef<DevicApiClient | null>(null);\n if (!clientRef.current && (apiKey || getTenantSession)) {\n clientRef.current = new DevicApiClient({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n }\n\n // Update client config if it changes\n useEffect(() => {\n if (clientRef.current && apiKey) {\n clientRef.current.setConfig({ apiKey, baseUrl });\n }\n }, [apiKey, baseUrl]);\n\n // Resume chat state based on realtime status.\n // Called after loading chat history to detect in-progress conversations.\n const resumeFromRealtimeStatus = useCallback(\n async (targetChatUid: string) => {\n if (!clientRef.current) return;\n try {\n const realtime = await clientRef.current.getRealtimeHistory(assistantId, targetChatUid);\n logRef.current.log('[useDevicChat] resumeFromRealtimeStatus:', realtime.status);\n\n // Update messages with realtime data (may be fresher than static history)\n if (realtime.chatHistory?.length) {\n setMessages(realtime.chatHistory);\n }\n mergeRecalledMemories(realtime.recalledMemories);\n setStatus(realtime.status);\n\n if (realtime.status === 'processing') {\n // Chat is still processing — resume polling\n setIsLoading(true);\n setShouldPoll(true);\n } else if (realtime.status === 'waiting_for_tool_response') {\n // Chat is waiting for tool response — resume polling to trigger tool handling\n setIsLoading(true);\n setShouldPoll(true);\n } else if (realtime.status === 'handed_off') {\n // Chat has an active handoff\n setIsLoading(true);\n setHandedOff(true);\n const subThreadId = realtime.handedOffSubThreadId || null;\n logRef.current.log('[useDevicChat] Resuming handoff state:', { subThreadId });\n if (subThreadId) {\n setHandedOffSubThreadId(subThreadId);\n }\n } else {\n // completed or error — just stop\n setIsLoading(false);\n }\n } catch (err) {\n // If realtime fetch fails (e.g. chat has no realtime entry), just stay idle\n logRef.current.warn('[useDevicChat] resumeFromRealtimeStatus failed:', err);\n setIsLoading(false);\n }\n },\n [assistantId, mergeRecalledMemories]\n );\n\n // Load initial chat history if chatUid prop is provided\n // This runs once on mount (or when initialChatUid changes) to fetch existing conversation\n const initialChatLoadedRef = useRef(false);\n useEffect(() => {\n if (initialChatUid && clientRef.current && !initialChatLoadedRef.current) {\n initialChatLoadedRef.current = true;\n\n const loadInitialChat = async () => {\n setIsLoading(true);\n setError(null);\n try {\n const history = await clientRef.current!.getChatHistory(\n assistantId,\n initialChatUid,\n { tenantId: resolvedTenantId }\n );\n setMessages(history.chatContent);\n mergeRecalledMemories(history.recalledMemories);\n setChatUid(initialChatUid);\n\n // Check realtime status to resume in-progress conversations\n await resumeFromRealtimeStatus(initialChatUid);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onErrorRef.current?.(error);\n setIsLoading(false);\n }\n };\n\n loadInitialChat();\n }\n }, [initialChatUid, assistantId, resolvedTenantId, resumeFromRealtimeStatus]);\n\n // Model interface hook\n const {\n toolSchemas,\n handleToolCalls,\n extractPendingToolCalls,\n } = useModelInterface({\n tools: modelInterfaceTools,\n onToolExecute: onToolCall,\n });\n\n // Pending widget calls awaiting user interaction\n const [pendingWidgetCalls, setPendingWidgetCalls] = useState<PendingWidgetCall[]>([]);\n const pendingWidgetCallsRef = useRef<PendingWidgetCall[]>([]);\n useEffect(() => {\n pendingWidgetCallsRef.current = pendingWidgetCalls;\n }, [pendingWidgetCalls]);\n\n // Polling hook - uses callbacks for side effects, return value not needed\n logRef.current.log('[useDevicChat] Render - shouldPoll:', shouldPoll, 'chatUid:', chatUid);\n usePolling(\n shouldPoll ? chatUid : null,\n async () => {\n logRef.current.log('[useDevicChat] fetchFn called, chatUid:', chatUid);\n if (!clientRef.current || !chatUid) {\n throw new Error('Cannot poll without client or chatUid');\n }\n const result = await clientRef.current.getRealtimeHistory(assistantId, chatUid);\n logRef.current.log('[useDevicChat] getRealtimeHistory result:', result);\n return result;\n },\n {\n interval: pollingInterval,\n enabled: shouldPoll,\n stopStatuses: [\n 'completed',\n 'error',\n 'waiting_for_tool_response',\n 'handed_off',\n 'limit_exceeded',\n ],\n onUpdate: async (data: RealtimeChatHistory) => {\n logRef.current.log('[useDevicChat] onUpdate called, status:', data.status);\n\n // Merge realtime data with optimistic messages.\n // When a server user message matches an optimistic one by text, adopt the\n // optimistic uid so React's key stays stable (avoids unmount/remount flicker).\n setMessages((prev) => {\n const normalize = (t?: string) => (t ?? '').trim();\n const optimisticUserByText = new Map(\n prev\n .filter((m) => m.role === 'user' && m.uid.startsWith('temp-'))\n .map((m) => [normalize(m.content?.message), m.uid])\n );\n\n const adoptedTempUids = new Set<string>();\n const merged = data.chatHistory.map((m) => {\n if (m.role === 'user') {\n const tempUid = optimisticUserByText.get(normalize(m.content?.message));\n if (tempUid) {\n adoptedTempUids.add(tempUid);\n // Keep the server uid around: recall anchors reference it.\n return { ...m, uid: tempUid, serverUid: m.uid };\n }\n }\n return m;\n });\n\n const mergedUIDs = new Set(merged.map((m) => m.uid));\n const optimistic = prev.filter(\n (m) => !mergedUIDs.has(m.uid) && !adoptedTempUids.has(m.uid)\n );\n\n return [...merged, ...optimistic];\n });\n // Surface recall events while the run is still processing, so the\n // \"recalled memories\" strip shows before the first response lands.\n mergeRecalledMemories(data.recalledMemories);\n setStatus(data.status);\n\n // Notify about new messages\n const lastMessage = data.chatHistory[data.chatHistory.length - 1];\n if (lastMessage && lastMessage.role === 'assistant') {\n onMessageReceivedRef.current?.(lastMessage);\n }\n\n // Handle model interface - check for pending tool calls\n if (data.status === 'waiting_for_tool_response' || data.pendingToolCalls?.length) {\n await handlePendingToolCalls(data);\n }\n },\n onStop: (data) => {\n logRef.current.log('[useDevicChat] onStop called, status:', data?.status);\n setShouldPoll(false);\n\n if (data?.status === 'limit_exceeded') {\n // The message was blocked by a tenant/subtenant usage limit before\n // reaching the LLM. Surface the details so the UI can show a banner.\n setIsLoading(false);\n const details: TenantLimitExceeded = data.limitExceeded || {\n message: 'Usage limit reached.',\n };\n setLimitExceeded(details);\n const err = new Error(\n details.message || 'Usage limit reached.'\n ) as Error & { errorType?: string; details?: TenantLimitExceeded };\n err.errorType = 'TENANT_LIMIT_EXCEEDED';\n err.details = details;\n setError(err);\n onErrorRef.current?.(err);\n } else if (data?.status === 'error') {\n setIsLoading(false);\n const err = new Error('Chat processing failed');\n setError(err);\n onErrorRef.current?.(err);\n } else if (data?.status === 'completed') {\n setIsLoading(false);\n } else if (data?.status === 'handed_off') {\n // Subagent is working — keep isLoading true so the UI stays in loading state.\n // Set handoff state directly from the realtime status.\n setHandedOff(true);\n\n const subThreadId = data.handedOffSubThreadId || null;\n logRef.current.log('[useDevicChat] Handoff state set:', { handedOff: true, subThreadId });\n if (subThreadId) {\n setHandedOffSubThreadId(subThreadId);\n }\n }\n // Note: waiting_for_tool_response is handled in onUpdate to avoid double execution\n },\n onError: (err) => {\n logRef.current.error('[useDevicChat] onError called:', err);\n setError(err);\n setIsLoading(false);\n setShouldPoll(false);\n onErrorRef.current?.(err);\n },\n debug,\n }\n );\n\n // Handle pending tool calls from model interface\n const handlePendingToolCalls = useCallback(\n async (data: RealtimeChatHistory) => {\n if (!clientRef.current || !chatUid) return;\n\n // Get pending tool calls\n const pendingCalls = data.pendingToolCalls || extractPendingToolCalls(data.chatHistory);\n\n if (pendingCalls.length === 0) return;\n\n try {\n // Execute client-side tools (partitioned into immediate responses and widget-driven)\n const { responses, widgetCalls } = await handleToolCalls(pendingCalls);\n\n // Queue widget-driven tool calls for user interaction\n if (widgetCalls.length > 0) {\n const existingIds = new Set(pendingWidgetCallsRef.current.map((c) => c.toolCall.id));\n const deduped = widgetCalls.filter((c) => !existingIds.has(c.toolCall.id));\n const next = [...pendingWidgetCallsRef.current, ...deduped];\n pendingWidgetCallsRef.current = next;\n setPendingWidgetCalls(next);\n // Stop polling while we wait for the user to submit the widget response.\n // The widget submission will re-trigger polling via submitWidgetResponse.\n setShouldPoll(false);\n setIsLoading(false);\n }\n\n if (responses.length > 0) {\n // Send tool responses back to the API\n await clientRef.current.sendToolResponses(assistantId, chatUid, responses);\n\n // Only resume polling if no widgets are blocking\n if (widgetCalls.length === 0) {\n setShouldPoll(true);\n setIsLoading(true);\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onErrorRef.current?.(error);\n }\n },\n [chatUid, assistantId, handleToolCalls, extractPendingToolCalls]\n );\n\n // Send a message\n const sendMessage = useCallback(\n async (\n message: string,\n sendOptions?: {\n files?: File[];\n metadata?: Record<string, any>;\n transcriptId?: string;\n tags?: string[];\n disabledIntegrations?: string[];\n }\n ) => {\n if (!clientRef.current) {\n const err = new Error(\n 'API client not configured. Please provide an API key.'\n );\n setError(err);\n onErrorRef.current?.(err);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n setLimitExceeded(null);\n setStatus('processing');\n\n // Add user message optimistically (show file names before upload)\n const userMessage: ChatMessage = {\n uid: `temp-${Date.now()}`,\n role: 'user',\n content: {\n message,\n files: sendOptions?.files?.map((f) => ({\n name: f.name,\n url: '',\n type: f.type.split('/')[0] || 'other',\n })),\n },\n timestamp: Date.now(),\n ...(sendOptions?.transcriptId && {\n transcriptId: sendOptions.transcriptId,\n }),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n onMessageSent?.(userMessage);\n\n try {\n // Upload files if provided\n let uploadedFiles: ChatFile[] | undefined;\n if (sendOptions?.files && sendOptions.files.length > 0) {\n logRef.current.log('[useDevicChat] Uploading files...');\n if (onFileUpload) {\n // Use custom upload handler\n uploadedFiles = await onFileUpload(sendOptions.files);\n } else {\n // Default: upload via Devic API\n const uploadResults = await Promise.all(\n sendOptions.files.map((file) => clientRef.current!.uploadFile(file))\n );\n uploadedFiles = uploadResults.map((r) => ({\n name: r.name,\n downloadUrl: r.downloadUrl,\n fileType: r.fileType as ChatFile['fileType'],\n }));\n }\n logRef.current.log('[useDevicChat] Files uploaded:', uploadedFiles);\n\n // Update optimistic message with download URLs\n setMessages((prev) =>\n prev.map((m) =>\n m.uid === userMessage.uid\n ? {\n ...m,\n content: {\n ...m.content,\n files: uploadedFiles!.map((f) => ({\n name: f.name,\n url: f.downloadUrl || '',\n type: f.fileType || 'other',\n })),\n },\n }\n : m\n )\n );\n }\n\n // Build request DTO\n const hasSubtenantMetadata =\n resolvedSubtenantMetadata &&\n Object.keys(resolvedSubtenantMetadata).length > 0;\n const dto = {\n message,\n chatUid: chatUid || undefined,\n files: uploadedFiles,\n metadata: {\n ...resolvedTenantMetadata,\n ...(hasSubtenantMetadata && {\n subtenantMetadata: resolvedSubtenantMetadata,\n }),\n ...sendOptions?.metadata,\n },\n tenantId: resolvedTenantId,\n ...(resolvedSubtenantId && { subtenantId: resolvedSubtenantId }),\n // Conversation tags: provider + hook + per-message, deduped\n ...(() => {\n const merged = Array.from(\n new Set([...resolvedTags, ...(sendOptions?.tags ?? [])])\n );\n return merged.length > 0 ? { tags: merged } : {};\n })(),\n enabledTools,\n // The end user's own apps that sit this message out. Sent only when\n // some are switched off: an older API ignores the field, and there is\n // no reason to put an empty array in every request.\n ...(() => {\n const off = sendOptions?.disabledIntegrations ?? disabledIntegrations;\n return off?.length ? { disabledIntegrations: off } : {};\n })(),\n // Include model interface tools if any\n ...(toolSchemas.length > 0 && { tools: toolSchemas }),\n // Link to the speech-to-text transcript that seeded this message, if any\n ...(sendOptions?.transcriptId && { transcriptId: sendOptions.transcriptId }),\n };\n\n // Send message in async mode\n logRef.current.log('[useDevicChat] Sending message async...');\n const response = await clientRef.current.sendMessageAsync(assistantId, dto);\n logRef.current.log('[useDevicChat] sendMessageAsync response:', response);\n\n // Update chat UID if this is a new chat\n if (response.chatUid && response.chatUid !== chatUid) {\n logRef.current.log('[useDevicChat] Setting chatUid:', response.chatUid);\n setChatUid(response.chatUid);\n onChatCreatedRef.current?.(response.chatUid);\n }\n\n // Start polling for results\n logRef.current.log('[useDevicChat] Setting shouldPoll to true');\n setShouldPoll(true);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n\n // A synchronous usage-limit block surfaces as HTTP 429 /\n // TENANT_LIMIT_EXCEEDED (sync send path). Async sends surface it via the\n // realtime `limit_exceeded` status instead — both are handled.\n if (\n err instanceof DevicApiError &&\n (err.statusCode === 429 || err.errorType === 'TENANT_LIMIT_EXCEEDED')\n ) {\n const details: TenantLimitExceeded =\n (err.details as TenantLimitExceeded) || { message: err.message };\n if (!details.message) details.message = err.message;\n setLimitExceeded(details);\n }\n\n setError(error);\n setIsLoading(false);\n setStatus('error');\n onErrorRef.current?.(error);\n\n // Remove optimistic user message on error\n setMessages((prev) => prev.filter((m) => m.uid !== userMessage.uid));\n }\n },\n [\n chatUid,\n assistantId,\n enabledTools,\n // Without this, the callback keeps the list from the render that created\n // it: switching an app off would not take effect until something else\n // happened to rebuild it.\n disabledIntegrations,\n resolvedTenantId,\n resolvedTenantMetadata,\n resolvedSubtenantId,\n resolvedSubtenantMetadata,\n resolvedTags,\n toolSchemas,\n onMessageSent,\n onFileUpload,\n ]\n );\n\n // Clear chat\n const clearChat = useCallback(() => {\n setShouldPoll(false);\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n setMessages([]);\n setChatUid(null);\n setIsLoading(false);\n setStatus('idle');\n setError(null);\n setLimitExceeded(null);\n setRecalledMemories([]);\n pendingWidgetCallsRef.current = [];\n setPendingWidgetCalls([]);\n }, []);\n\n // Load existing chat\n const loadChat = useCallback(\n async (loadChatUid: string) => {\n if (!clientRef.current) {\n const err = new Error('API client not configured');\n setError(err);\n onErrorRef.current?.(err);\n return;\n }\n\n // Reset any active polling/handoff state from previous conversation\n setShouldPoll(false);\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n pendingWidgetCallsRef.current = [];\n setPendingWidgetCalls([]);\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n\n setIsLoading(true);\n setError(null);\n setRecalledMemories([]);\n\n try {\n const history = await clientRef.current.getChatHistory(\n assistantId,\n loadChatUid,\n { tenantId: resolvedTenantId }\n );\n\n setMessages(history.chatContent);\n mergeRecalledMemories(history.recalledMemories);\n setChatUid(loadChatUid);\n\n // Check realtime status to resume in-progress conversations\n await resumeFromRealtimeStatus(loadChatUid);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onErrorRef.current?.(error);\n setIsLoading(false);\n }\n },\n [assistantId, resolvedTenantId, resumeFromRealtimeStatus, mergeRecalledMemories]\n );\n\n // Handoff polling: while handedOff is true, poll the realtime endpoint every\n // 5s (or the configured cadence) to detect when the parent thread is no\n // longer in handed_off state.\n useEffect(() => {\n if (!handedOff || !chatUid || !clientRef.current) return;\n\n const pollHandoff = async () => {\n try {\n const realtime = await clientRef.current!.getRealtimeHistory(assistantId, chatUid!);\n logRef.current.log('[useDevicChat] Handoff poll - realtime status:', realtime.status);\n if (realtime.status !== 'handed_off') {\n // Handoff completed — clear handoff state and resume main polling\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n // Resume main polling to pick up the parent thread's continuation\n setShouldPoll(true);\n }\n } catch {}\n };\n\n handoffPollRef.current = setInterval(pollHandoff, handoffPollingInterval);\n return () => {\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n };\n }, [handedOff, chatUid, assistantId, handoffPollingInterval]);\n\n // Called by HandoffSubagentWidget when the subthread reaches a terminal state\n const onHandoffCompleted = useCallback(() => {\n logRef.current.log('[useDevicChat] onHandoffCompleted called');\n // Clear the handoff polling\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n // Clear handoff state and resume main polling\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n setShouldPoll(true);\n }, []);\n\n // Submit a response for a pending widget tool call\n const submitWidgetResponse = useCallback(\n async (toolCallId: string, response: any) => {\n const uid = chatUidRef.current;\n if (!clientRef.current || !uid) return;\n\n // Check pending widgets via ref (state updates are async)\n const current = pendingWidgetCallsRef.current;\n const found = current.some((c) => c.toolCall.id === toolCallId);\n if (!found) return;\n\n // Remove the widget call from pending list\n const remaining = current.filter((c) => c.toolCall.id !== toolCallId);\n pendingWidgetCallsRef.current = remaining;\n setPendingWidgetCalls(remaining);\n\n try {\n logRef.current.log('[useDevicChat] sending widget tool response', toolCallId);\n await clientRef.current.sendToolResponses(assistantId, uid, [\n { tool_call_id: toolCallId, content: response, role: 'tool' },\n ]);\n // Resume polling only if no more widget calls are blocking\n if (remaining.length === 0) {\n setShouldPoll(true);\n setIsLoading(true);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n logRef.current.error('[useDevicChat] submitWidgetResponse failed', error);\n setError(error);\n onErrorRef.current?.(error);\n }\n },\n [assistantId]\n );\n\n // Cancel a pending widget tool call (sends an error response to the model)\n const cancelWidgetCall = useCallback(\n async (toolCallId: string, reason?: string) => {\n await submitWidgetResponse(toolCallId, {\n error: reason || 'User cancelled the tool call',\n });\n },\n [submitWidgetResponse]\n );\n\n // Stop current conversation — calls the server-side stop endpoint\n // then stops polling and resets loading state.\n const stopChat = useCallback(async () => {\n const uid = chatUidRef.current;\n logRef.current.log('[useDevicChat] stopChat called, chatUid:', uid);\n if (clientRef.current && uid) {\n try {\n await clientRef.current.stopChat(assistantId, uid);\n logRef.current.log('[useDevicChat] stopChat API call succeeded');\n } catch (err) {\n logRef.current.warn('[useDevicChat] stopChat API call failed:', err);\n }\n }\n setShouldPoll(false);\n setIsLoading(false);\n setStatus('idle');\n }, [assistantId]);\n\n return {\n messages,\n chatUid,\n isLoading,\n status,\n error,\n limitExceeded,\n recalledMemories,\n handedOff,\n handedOffSubThreadId,\n sendMessage,\n clearChat,\n loadChat,\n onHandoffCompleted,\n stopChat,\n pendingWidgetCalls,\n submitWidgetResponse,\n cancelWidgetCall,\n };\n}\n"],"names":["useOptionalDevicContext","useMemo","resolvePollingInterval","createLogger","useRef","useState","useCallback","useEffect","DevicApiClient","useModelInterface","usePolling","DevicApiError"],"mappings":"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"}
1
+ {"version":3,"file":"useDevicChat.js","sources":["../../../../src/hooks/useDevicChat.ts"],"sourcesContent":["import { useState, useCallback, useEffect, useRef, useMemo } from 'react';\nimport { useOptionalDevicContext } from '../provider';\nimport type { TenantMetadata, SubtenantMetadata } from '../provider';\nimport { DevicApiClient, DevicApiError } from '../api/client';\nimport { usePolling, resolvePollingInterval } from './usePolling';\nimport { useModelInterface, type PendingWidgetCall } from './useModelInterface';\nimport { createLogger } from '../utils/logger';\nimport type {\n ChatMessage,\n ChatFile,\n ModelInterfaceTool,\n RealtimeChatHistory,\n RealtimeStatus,\n RecalledMemoryRecord,\n TenantLimitExceeded,\n} from '../api/types';\n\n/**\n * Cadence for the handoff watch, which only waits for the parent thread to\n * leave `handed_off` and so does not need the main conversation's rhythm.\n * A configured `pollingInterval` still wins over it.\n */\nconst DEFAULT_HANDOFF_POLL_INTERVAL_MS = 5000;\n\nexport interface UseDevicChatOptions {\n /**\n * Assistant identifier\n */\n assistantId: string;\n\n /**\n * Existing chat UID to continue a conversation\n */\n chatUid?: string;\n\n /**\n * API key (overrides provider context)\n */\n apiKey?: string;\n\n /**\n * Base URL (overrides provider context)\n */\n baseUrl?: string;\n\n /**\n * Tenant ID for multi-tenant environments\n */\n tenantId?: string;\n\n /**\n * Tenant metadata (e.g. { name, email, imageUrl })\n */\n tenantMetadata?: TenantMetadata;\n\n /**\n * Subtenant ID identifying a user/entity inside the tenant\n */\n subtenantId?: string;\n\n /**\n * Subtenant metadata (e.g. { id, name, email, imageUrl })\n */\n subtenantMetadata?: SubtenantMetadata;\n\n /**\n * Tags applied to the conversation. Sent as the top-level `tags` of each\n * message (distinct from metadata). Falls back to the DevicProvider's `tags`\n * and is merged (deduped) with any per-message tags passed to `sendMessage`.\n */\n tags?: string[];\n\n /**\n * Tools enabled from the assistant's configured tool groups\n */\n enabledTools?: string[];\n\n /**\n * Apps the end user connected that should sit out the messages sent from\n * here, by slug (`[\"gmail\"]`).\n *\n * A deny list over their own connected apps, not over the assistant's tools:\n * what is not named stays available. Sent with every message while it is set,\n * so it lasts as long as the caller keeps it set — the server keeps nothing\n * and the account is never disconnected.\n */\n disabledIntegrations?: string[];\n\n /**\n * Client-side tools for model interface protocol\n */\n modelInterfaceTools?: ModelInterfaceTool[];\n\n /**\n * How often (ms) the conversation in progress is polled for new content.\n * Overrides the DevicProvider's `pollingInterval`. Values below 250 ms are\n * clamped.\n * @default 1000\n */\n pollingInterval?: number;\n\n /**\n * Callback when a message is sent\n */\n onMessageSent?: (message: ChatMessage) => void;\n\n /**\n * Callback when a message is received\n */\n onMessageReceived?: (message: ChatMessage) => void;\n\n /**\n * Callback when a tool is called\n */\n onToolCall?: (toolName: string, params: any) => void;\n\n /**\n * Callback when an error occurs\n */\n onError?: (error: Error) => void;\n\n /**\n * Callback when a new chat is created\n */\n onChatCreated?: (chatUid: string) => void;\n\n /**\n * Custom file upload handler. When provided, replaces the default\n * upload to Devic API. Receives the raw File objects and must return\n * an array of ChatFile with downloadUrl set.\n */\n onFileUpload?: (files: File[]) => Promise<ChatFile[]>;\n\n /**\n * Enable debug logging to the browser console.\n * Overrides the provider-level debug setting when provided.\n * @default false\n */\n debug?: boolean;\n}\n\nexport interface UseDevicChatResult {\n /**\n * Current chat messages\n */\n messages: ChatMessage[];\n\n /**\n * Current chat UID\n */\n chatUid: string | null;\n\n /**\n * Whether a message is being processed\n */\n isLoading: boolean;\n\n /**\n * Current status\n */\n status: RealtimeStatus | 'idle';\n\n /**\n * Last error\n */\n error: Error | null;\n\n /**\n * Set when the last message was blocked by a tenant/subtenant usage limit\n * (HTTP 429 / realtime status `limit_exceeded`). Carries the blocking rule,\n * current vs. limit and when the window resets. `null` while not limited.\n * Cleared when a new message is sent or the chat is cleared.\n */\n limitExceeded: TenantLimitExceeded | null;\n\n /**\n * Structured long-term-memory recall events of the conversation, streamed\n * in while the assistant is still processing (via the realtime poll) and\n * hydrated from the persisted history on load. Empty for assistants\n * without memory.\n */\n recalledMemories: RecalledMemoryRecord[];\n\n /**\n * Whether the assistant has handed off to a subagent\n */\n handedOff: boolean;\n\n /**\n * The subthread ID when a handoff is active\n */\n handedOffSubThreadId: string | null;\n\n /**\n * Send a message\n */\n sendMessage: (\n message: string,\n options?: {\n files?: File[];\n metadata?: Record<string, any>;\n /** Id of a speech-to-text transcript that seeded this message. */\n transcriptId?: string;\n /** Per-message tags, merged (deduped) with the resolved conversation tags. */\n tags?: string[];\n /**\n * Connected apps to leave out of this one message, by slug. Replaces the\n * hook's own `disabledIntegrations` rather than adding to it, so a caller\n * can send one message with everything on by passing `[]`.\n */\n disabledIntegrations?: string[];\n }\n ) => Promise<void>;\n\n /**\n * Clear the chat and start a new conversation\n */\n clearChat: () => void;\n\n /**\n * Load an existing chat\n */\n loadChat: (chatUid: string) => Promise<void>;\n\n /**\n * Called when the handoff subagent completes.\n * Triggers reload of full chat content.\n */\n onHandoffCompleted: () => void;\n\n /**\n * Stop the current conversation processing (client-side only).\n * Stops polling and resets loading state.\n */\n stopChat: () => void;\n\n /**\n * Pending tool calls that require user interaction via a response widget\n */\n pendingWidgetCalls: PendingWidgetCall[];\n\n /**\n * Submit a response for a pending widget tool call.\n * Sends the response to the API and resumes the conversation.\n */\n submitWidgetResponse: (toolCallId: string, response: any) => Promise<void>;\n\n /**\n * Cancel a pending widget tool call.\n * Sends an error response so the model can continue.\n */\n cancelWidgetCall: (toolCallId: string, reason?: string) => Promise<void>;\n}\n\n/**\n * Main hook for managing chat with a Devic assistant\n *\n * @example\n * ```tsx\n * const {\n * messages,\n * isLoading,\n * sendMessage,\n * } = useDevicChat({\n * assistantId: 'my-assistant',\n * modelInterfaceTools: [\n * {\n * toolName: 'get_user_location',\n * schema: { ... },\n * callback: async () => ({ lat: 40.7, lng: -74.0 })\n * }\n * ],\n * onMessageReceived: (msg) => console.log('Received:', msg),\n * });\n * ```\n */\nexport function useDevicChat(options: UseDevicChatOptions): UseDevicChatResult {\n const {\n assistantId,\n chatUid: initialChatUid,\n apiKey: propsApiKey,\n baseUrl: propsBaseUrl,\n tenantId,\n tenantMetadata,\n subtenantId,\n subtenantMetadata,\n tags,\n enabledTools,\n disabledIntegrations,\n modelInterfaceTools = [],\n pollingInterval: propsPollingInterval,\n onMessageSent,\n onMessageReceived,\n onToolCall,\n onError,\n onChatCreated,\n onFileUpload,\n debug: propsDebug,\n } = options;\n\n // Get context (may be null if not wrapped in provider)\n const context = useOptionalDevicContext();\n\n // Resolve configuration\n const apiKey = propsApiKey || context?.apiKey;\n const getTenantSession = context?.getTenantSession;\n const onSessionExpired = context?.onSessionExpired;\n const baseUrl = propsBaseUrl || context?.baseUrl || 'https://api.devic.ai';\n const resolvedTenantId = tenantId || context?.tenantId;\n const resolvedTenantMetadata = { ...context?.tenantMetadata, ...tenantMetadata };\n const resolvedSubtenantId = subtenantId || context?.subtenantId;\n const resolvedSubtenantMetadata = {\n ...context?.subtenantMetadata,\n ...subtenantMetadata,\n };\n // Provider tags + hook tags, deduped. Per-message tags are merged at send time.\n const resolvedTags = useMemo(\n () => Array.from(new Set([...(context?.tags ?? []), ...(tags ?? [])])),\n [context?.tags, tags]\n );\n const pollingInterval = resolvePollingInterval(\n propsPollingInterval,\n context?.pollingInterval\n );\n const handoffPollingInterval = resolvePollingInterval(\n propsPollingInterval,\n context?.pollingInterval,\n DEFAULT_HANDOFF_POLL_INTERVAL_MS\n );\n const debug = propsDebug ?? context?.debug ?? false;\n const log = useMemo(() => createLogger(debug), [debug]);\n const logRef = useRef(log);\n logRef.current = log;\n\n // State\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [chatUid, setChatUid] = useState<string | null>(initialChatUid || null);\n const [isLoading, setIsLoading] = useState(false);\n const [status, setStatus] = useState<RealtimeStatus | 'idle'>('idle');\n const [error, setError] = useState<Error | null>(null);\n const [limitExceeded, setLimitExceeded] = useState<TenantLimitExceeded | null>(\n null\n );\n\n // Long-term-memory recall events of the conversation. The realtime blob\n // only carries the in-flight run's records, so incoming batches merge (by\n // uid) instead of replacing — earlier runs' recalls stay visible.\n const [recalledMemories, setRecalledMemories] = useState<RecalledMemoryRecord[]>([]);\n const mergeRecalledMemories = useCallback(\n (incoming?: RecalledMemoryRecord[]) => {\n if (!incoming?.length) return;\n setRecalledMemories((prev) => {\n const known = new Set(prev.map((r) => r.uid));\n const fresh = incoming.filter((r) => !known.has(r.uid));\n return fresh.length ? [...prev, ...fresh] : prev;\n });\n },\n []\n );\n\n // Handoff state\n const [handedOff, setHandedOff] = useState(false);\n const [handedOffSubThreadId, setHandedOffSubThreadId] = useState<string | null>(null);\n const handoffPollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n // Polling state\n const [shouldPoll, setShouldPoll] = useState(false);\n\n // Keep a ref to chatUid so async callbacks always read the latest value\n const chatUidRef = useRef(chatUid);\n chatUidRef.current = chatUid;\n\n // Refs for callbacks\n const onMessageReceivedRef = useRef(onMessageReceived);\n const onErrorRef = useRef(onError);\n const onChatCreatedRef = useRef(onChatCreated);\n\n useEffect(() => {\n onMessageReceivedRef.current = onMessageReceived;\n onErrorRef.current = onError;\n onChatCreatedRef.current = onChatCreated;\n });\n\n // Create API client\n const clientRef = useRef<DevicApiClient | null>(null);\n if (!clientRef.current && (apiKey || getTenantSession)) {\n clientRef.current = new DevicApiClient({ apiKey, baseUrl, getTenantSession, onSessionExpired });\n }\n\n // Update client config if it changes\n useEffect(() => {\n if (clientRef.current && apiKey) {\n clientRef.current.setConfig({ apiKey, baseUrl });\n }\n }, [apiKey, baseUrl]);\n\n // Resume chat state based on realtime status.\n // Called after loading chat history to detect in-progress conversations.\n const resumeFromRealtimeStatus = useCallback(\n async (targetChatUid: string) => {\n if (!clientRef.current) return;\n try {\n const realtime = await clientRef.current.getRealtimeHistory(assistantId, targetChatUid);\n logRef.current.log('[useDevicChat] resumeFromRealtimeStatus:', realtime.status);\n\n // Update messages with realtime data (may be fresher than static history)\n if (realtime.chatHistory?.length) {\n setMessages(realtime.chatHistory);\n }\n mergeRecalledMemories(realtime.recalledMemories);\n setStatus(realtime.status);\n\n if (realtime.status === 'processing') {\n // Chat is still processing — resume polling\n setIsLoading(true);\n setShouldPoll(true);\n } else if (realtime.status === 'waiting_for_tool_response') {\n // Chat is waiting for tool response — resume polling to trigger tool handling\n setIsLoading(true);\n setShouldPoll(true);\n } else if (realtime.status === 'handed_off') {\n // Chat has an active handoff\n setIsLoading(true);\n setHandedOff(true);\n const subThreadId = realtime.handedOffSubThreadId || null;\n logRef.current.log('[useDevicChat] Resuming handoff state:', { subThreadId });\n if (subThreadId) {\n setHandedOffSubThreadId(subThreadId);\n }\n } else {\n // completed or error — just stop\n setIsLoading(false);\n }\n } catch (err) {\n // If realtime fetch fails (e.g. chat has no realtime entry), just stay idle\n logRef.current.warn('[useDevicChat] resumeFromRealtimeStatus failed:', err);\n setIsLoading(false);\n }\n },\n [assistantId, mergeRecalledMemories]\n );\n\n // Load initial chat history if chatUid prop is provided\n // This runs once on mount (or when initialChatUid changes) to fetch existing conversation\n const initialChatLoadedRef = useRef(false);\n useEffect(() => {\n if (initialChatUid && clientRef.current && !initialChatLoadedRef.current) {\n initialChatLoadedRef.current = true;\n\n const loadInitialChat = async () => {\n setIsLoading(true);\n setError(null);\n try {\n const history = await clientRef.current!.getChatHistory(\n assistantId,\n initialChatUid,\n { tenantId: resolvedTenantId }\n );\n setMessages(history.chatContent);\n mergeRecalledMemories(history.recalledMemories);\n setChatUid(initialChatUid);\n\n // Check realtime status to resume in-progress conversations\n await resumeFromRealtimeStatus(initialChatUid);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onErrorRef.current?.(error);\n setIsLoading(false);\n }\n };\n\n loadInitialChat();\n }\n }, [initialChatUid, assistantId, resolvedTenantId, resumeFromRealtimeStatus]);\n\n // Model interface hook\n const {\n toolSchemas,\n handleToolCalls,\n extractPendingToolCalls,\n } = useModelInterface({\n tools: modelInterfaceTools,\n onToolExecute: onToolCall,\n });\n\n // Pending widget calls awaiting user interaction\n const [pendingWidgetCalls, setPendingWidgetCalls] = useState<PendingWidgetCall[]>([]);\n const pendingWidgetCallsRef = useRef<PendingWidgetCall[]>([]);\n useEffect(() => {\n pendingWidgetCallsRef.current = pendingWidgetCalls;\n }, [pendingWidgetCalls]);\n\n // Polling hook - uses callbacks for side effects, return value not needed\n logRef.current.log('[useDevicChat] Render - shouldPoll:', shouldPoll, 'chatUid:', chatUid);\n usePolling(\n shouldPoll ? chatUid : null,\n async () => {\n logRef.current.log('[useDevicChat] fetchFn called, chatUid:', chatUid);\n if (!clientRef.current || !chatUid) {\n throw new Error('Cannot poll without client or chatUid');\n }\n const result = await clientRef.current.getRealtimeHistory(assistantId, chatUid);\n logRef.current.log('[useDevicChat] getRealtimeHistory result:', result);\n return result;\n },\n {\n interval: pollingInterval,\n enabled: shouldPoll,\n stopStatuses: [\n 'completed',\n 'error',\n 'waiting_for_tool_response',\n 'handed_off',\n 'limit_exceeded',\n ],\n onUpdate: async (data: RealtimeChatHistory) => {\n logRef.current.log('[useDevicChat] onUpdate called, status:', data.status);\n\n // Merge realtime data with optimistic messages.\n // When a server user message matches an optimistic one by text, adopt the\n // optimistic uid so React's key stays stable (avoids unmount/remount flicker).\n setMessages((prev) => {\n const normalize = (t?: string) => (t ?? '').trim();\n const optimisticUserByText = new Map(\n prev\n .filter((m) => m.role === 'user' && m.uid.startsWith('temp-'))\n .map((m) => [normalize(m.content?.message), m.uid])\n );\n\n const adoptedTempUids = new Set<string>();\n const merged = data.chatHistory.map((m) => {\n if (m.role === 'user') {\n const tempUid = optimisticUserByText.get(normalize(m.content?.message));\n if (tempUid) {\n adoptedTempUids.add(tempUid);\n // Keep the server uid around: recall anchors reference it.\n return { ...m, uid: tempUid, serverUid: m.uid };\n }\n }\n return m;\n });\n\n const mergedUIDs = new Set(merged.map((m) => m.uid));\n const optimistic = prev.filter(\n (m) => !mergedUIDs.has(m.uid) && !adoptedTempUids.has(m.uid)\n );\n\n return [...merged, ...optimistic];\n });\n // Surface recall events while the run is still processing, so the\n // \"recalled memories\" strip shows before the first response lands.\n mergeRecalledMemories(data.recalledMemories);\n setStatus(data.status);\n\n // Notify about new messages\n const lastMessage = data.chatHistory[data.chatHistory.length - 1];\n if (lastMessage && lastMessage.role === 'assistant') {\n onMessageReceivedRef.current?.(lastMessage);\n }\n\n // Handle model interface - check for pending tool calls\n if (data.status === 'waiting_for_tool_response' || data.pendingToolCalls?.length) {\n await handlePendingToolCalls(data);\n }\n },\n onStop: (data) => {\n logRef.current.log('[useDevicChat] onStop called, status:', data?.status);\n setShouldPoll(false);\n\n if (data?.status === 'limit_exceeded') {\n // The message was blocked by a tenant/subtenant usage limit before\n // reaching the LLM. Surface the details so the UI can show a banner.\n setIsLoading(false);\n const details: TenantLimitExceeded = data.limitExceeded || {\n message: 'Usage limit reached.',\n };\n setLimitExceeded(details);\n const err = new Error(\n details.message || 'Usage limit reached.'\n ) as Error & { errorType?: string; details?: TenantLimitExceeded };\n err.errorType = 'TENANT_LIMIT_EXCEEDED';\n err.details = details;\n setError(err);\n onErrorRef.current?.(err);\n } else if (data?.status === 'error') {\n setIsLoading(false);\n const err = new Error('Chat processing failed');\n setError(err);\n onErrorRef.current?.(err);\n } else if (data?.status === 'completed') {\n setIsLoading(false);\n } else if (data?.status === 'handed_off') {\n // Subagent is working — keep isLoading true so the UI stays in loading state.\n // Set handoff state directly from the realtime status.\n setHandedOff(true);\n\n const subThreadId = data.handedOffSubThreadId || null;\n logRef.current.log('[useDevicChat] Handoff state set:', { handedOff: true, subThreadId });\n if (subThreadId) {\n setHandedOffSubThreadId(subThreadId);\n }\n }\n // Note: waiting_for_tool_response is handled in onUpdate to avoid double execution\n },\n onError: (err) => {\n logRef.current.error('[useDevicChat] onError called:', err);\n setError(err);\n setIsLoading(false);\n setShouldPoll(false);\n onErrorRef.current?.(err);\n },\n debug,\n }\n );\n\n // Handle pending tool calls from model interface\n const handlePendingToolCalls = useCallback(\n async (data: RealtimeChatHistory) => {\n if (!clientRef.current || !chatUid) return;\n\n // Get pending tool calls\n const pendingCalls = data.pendingToolCalls || extractPendingToolCalls(data.chatHistory);\n\n if (pendingCalls.length === 0) return;\n\n try {\n // Execute client-side tools (partitioned into immediate responses and widget-driven)\n const { responses, widgetCalls } = await handleToolCalls(pendingCalls);\n\n // Queue widget-driven tool calls for user interaction\n if (widgetCalls.length > 0) {\n const existingIds = new Set(pendingWidgetCallsRef.current.map((c) => c.toolCall.id));\n const deduped = widgetCalls.filter((c) => !existingIds.has(c.toolCall.id));\n const next = [...pendingWidgetCallsRef.current, ...deduped];\n pendingWidgetCallsRef.current = next;\n setPendingWidgetCalls(next);\n // Stop polling while we wait for the user to submit the widget response.\n // The widget submission will re-trigger polling via submitWidgetResponse.\n setShouldPoll(false);\n setIsLoading(false);\n }\n\n if (responses.length > 0) {\n // Send tool responses back to the API, restating the tools so the\n // continuation keeps them on offer\n await clientRef.current.sendToolResponses(\n assistantId,\n chatUid,\n responses,\n toolSchemas\n );\n\n // Only resume polling if no widgets are blocking\n if (widgetCalls.length === 0) {\n setShouldPoll(true);\n setIsLoading(true);\n }\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onErrorRef.current?.(error);\n }\n },\n [chatUid, assistantId, handleToolCalls, extractPendingToolCalls, toolSchemas]\n );\n\n // Send a message\n const sendMessage = useCallback(\n async (\n message: string,\n sendOptions?: {\n files?: File[];\n metadata?: Record<string, any>;\n transcriptId?: string;\n tags?: string[];\n disabledIntegrations?: string[];\n }\n ) => {\n if (!clientRef.current) {\n const err = new Error(\n 'API client not configured. Please provide an API key.'\n );\n setError(err);\n onErrorRef.current?.(err);\n return;\n }\n\n setIsLoading(true);\n setError(null);\n setLimitExceeded(null);\n setStatus('processing');\n\n // Add user message optimistically (show file names before upload)\n const userMessage: ChatMessage = {\n uid: `temp-${Date.now()}`,\n role: 'user',\n content: {\n message,\n files: sendOptions?.files?.map((f) => ({\n name: f.name,\n url: '',\n type: f.type.split('/')[0] || 'other',\n })),\n },\n timestamp: Date.now(),\n ...(sendOptions?.transcriptId && {\n transcriptId: sendOptions.transcriptId,\n }),\n };\n\n setMessages((prev) => [...prev, userMessage]);\n onMessageSent?.(userMessage);\n\n try {\n // Upload files if provided\n let uploadedFiles: ChatFile[] | undefined;\n if (sendOptions?.files && sendOptions.files.length > 0) {\n logRef.current.log('[useDevicChat] Uploading files...');\n if (onFileUpload) {\n // Use custom upload handler\n uploadedFiles = await onFileUpload(sendOptions.files);\n } else {\n // Default: upload via Devic API\n const uploadResults = await Promise.all(\n sendOptions.files.map((file) => clientRef.current!.uploadFile(file))\n );\n uploadedFiles = uploadResults.map((r) => ({\n name: r.name,\n downloadUrl: r.downloadUrl,\n fileType: r.fileType as ChatFile['fileType'],\n }));\n }\n logRef.current.log('[useDevicChat] Files uploaded:', uploadedFiles);\n\n // Update optimistic message with download URLs\n setMessages((prev) =>\n prev.map((m) =>\n m.uid === userMessage.uid\n ? {\n ...m,\n content: {\n ...m.content,\n files: uploadedFiles!.map((f) => ({\n name: f.name,\n url: f.downloadUrl || '',\n type: f.fileType || 'other',\n })),\n },\n }\n : m\n )\n );\n }\n\n // Build request DTO\n const hasSubtenantMetadata =\n resolvedSubtenantMetadata &&\n Object.keys(resolvedSubtenantMetadata).length > 0;\n const dto = {\n message,\n chatUid: chatUid || undefined,\n files: uploadedFiles,\n metadata: {\n ...resolvedTenantMetadata,\n ...(hasSubtenantMetadata && {\n subtenantMetadata: resolvedSubtenantMetadata,\n }),\n ...sendOptions?.metadata,\n },\n tenantId: resolvedTenantId,\n ...(resolvedSubtenantId && { subtenantId: resolvedSubtenantId }),\n // Conversation tags: provider + hook + per-message, deduped\n ...(() => {\n const merged = Array.from(\n new Set([...resolvedTags, ...(sendOptions?.tags ?? [])])\n );\n return merged.length > 0 ? { tags: merged } : {};\n })(),\n enabledTools,\n // The end user's own apps that sit this message out. Sent only when\n // some are switched off: an older API ignores the field, and there is\n // no reason to put an empty array in every request.\n ...(() => {\n const off = sendOptions?.disabledIntegrations ?? disabledIntegrations;\n return off?.length ? { disabledIntegrations: off } : {};\n })(),\n // Include model interface tools if any\n ...(toolSchemas.length > 0 && { tools: toolSchemas }),\n // Link to the speech-to-text transcript that seeded this message, if any\n ...(sendOptions?.transcriptId && { transcriptId: sendOptions.transcriptId }),\n };\n\n // Send message in async mode\n logRef.current.log('[useDevicChat] Sending message async...');\n const response = await clientRef.current.sendMessageAsync(assistantId, dto);\n logRef.current.log('[useDevicChat] sendMessageAsync response:', response);\n\n // Update chat UID if this is a new chat\n if (response.chatUid && response.chatUid !== chatUid) {\n logRef.current.log('[useDevicChat] Setting chatUid:', response.chatUid);\n setChatUid(response.chatUid);\n onChatCreatedRef.current?.(response.chatUid);\n }\n\n // Start polling for results\n logRef.current.log('[useDevicChat] Setting shouldPoll to true');\n setShouldPoll(true);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n\n // A synchronous usage-limit block surfaces as HTTP 429 /\n // TENANT_LIMIT_EXCEEDED (sync send path). Async sends surface it via the\n // realtime `limit_exceeded` status instead — both are handled.\n if (\n err instanceof DevicApiError &&\n (err.statusCode === 429 || err.errorType === 'TENANT_LIMIT_EXCEEDED')\n ) {\n const details: TenantLimitExceeded =\n (err.details as TenantLimitExceeded) || { message: err.message };\n if (!details.message) details.message = err.message;\n setLimitExceeded(details);\n }\n\n setError(error);\n setIsLoading(false);\n setStatus('error');\n onErrorRef.current?.(error);\n\n // Remove optimistic user message on error\n setMessages((prev) => prev.filter((m) => m.uid !== userMessage.uid));\n }\n },\n [\n chatUid,\n assistantId,\n enabledTools,\n // Without this, the callback keeps the list from the render that created\n // it: switching an app off would not take effect until something else\n // happened to rebuild it.\n disabledIntegrations,\n resolvedTenantId,\n resolvedTenantMetadata,\n resolvedSubtenantId,\n resolvedSubtenantMetadata,\n resolvedTags,\n toolSchemas,\n onMessageSent,\n onFileUpload,\n ]\n );\n\n // Clear chat\n const clearChat = useCallback(() => {\n setShouldPoll(false);\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n setMessages([]);\n setChatUid(null);\n setIsLoading(false);\n setStatus('idle');\n setError(null);\n setLimitExceeded(null);\n setRecalledMemories([]);\n pendingWidgetCallsRef.current = [];\n setPendingWidgetCalls([]);\n }, []);\n\n // Load existing chat\n const loadChat = useCallback(\n async (loadChatUid: string) => {\n if (!clientRef.current) {\n const err = new Error('API client not configured');\n setError(err);\n onErrorRef.current?.(err);\n return;\n }\n\n // Reset any active polling/handoff state from previous conversation\n setShouldPoll(false);\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n pendingWidgetCallsRef.current = [];\n setPendingWidgetCalls([]);\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n\n setIsLoading(true);\n setError(null);\n setRecalledMemories([]);\n\n try {\n const history = await clientRef.current.getChatHistory(\n assistantId,\n loadChatUid,\n { tenantId: resolvedTenantId }\n );\n\n setMessages(history.chatContent);\n mergeRecalledMemories(history.recalledMemories);\n setChatUid(loadChatUid);\n\n // Check realtime status to resume in-progress conversations\n await resumeFromRealtimeStatus(loadChatUid);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n setError(error);\n onErrorRef.current?.(error);\n setIsLoading(false);\n }\n },\n [assistantId, resolvedTenantId, resumeFromRealtimeStatus, mergeRecalledMemories]\n );\n\n // Handoff polling: while handedOff is true, poll the realtime endpoint every\n // 5s (or the configured cadence) to detect when the parent thread is no\n // longer in handed_off state.\n useEffect(() => {\n if (!handedOff || !chatUid || !clientRef.current) return;\n\n const pollHandoff = async () => {\n try {\n const realtime = await clientRef.current!.getRealtimeHistory(assistantId, chatUid!);\n logRef.current.log('[useDevicChat] Handoff poll - realtime status:', realtime.status);\n if (realtime.status !== 'handed_off') {\n // Handoff completed — clear handoff state and resume main polling\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n // Resume main polling to pick up the parent thread's continuation\n setShouldPoll(true);\n }\n } catch {}\n };\n\n handoffPollRef.current = setInterval(pollHandoff, handoffPollingInterval);\n return () => {\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n };\n }, [handedOff, chatUid, assistantId, handoffPollingInterval]);\n\n // Called by HandoffSubagentWidget when the subthread reaches a terminal state\n const onHandoffCompleted = useCallback(() => {\n logRef.current.log('[useDevicChat] onHandoffCompleted called');\n // Clear the handoff polling\n if (handoffPollRef.current) {\n clearInterval(handoffPollRef.current);\n handoffPollRef.current = null;\n }\n // Clear handoff state and resume main polling\n setHandedOff(false);\n setHandedOffSubThreadId(null);\n setShouldPoll(true);\n }, []);\n\n // Submit a response for a pending widget tool call\n const submitWidgetResponse = useCallback(\n async (toolCallId: string, response: any) => {\n const uid = chatUidRef.current;\n if (!clientRef.current || !uid) return;\n\n // Check pending widgets via ref (state updates are async)\n const current = pendingWidgetCallsRef.current;\n const found = current.some((c) => c.toolCall.id === toolCallId);\n if (!found) return;\n\n // Remove the widget call from pending list\n const remaining = current.filter((c) => c.toolCall.id !== toolCallId);\n pendingWidgetCallsRef.current = remaining;\n setPendingWidgetCalls(remaining);\n\n try {\n logRef.current.log('[useDevicChat] sending widget tool response', toolCallId);\n await clientRef.current.sendToolResponses(\n assistantId,\n uid,\n [{ tool_call_id: toolCallId, content: response, role: 'tool' }],\n toolSchemas\n );\n // Resume polling only if no more widget calls are blocking\n if (remaining.length === 0) {\n setShouldPoll(true);\n setIsLoading(true);\n }\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n logRef.current.error('[useDevicChat] submitWidgetResponse failed', error);\n setError(error);\n onErrorRef.current?.(error);\n }\n },\n [assistantId, toolSchemas]\n );\n\n // Cancel a pending widget tool call (sends an error response to the model)\n const cancelWidgetCall = useCallback(\n async (toolCallId: string, reason?: string) => {\n await submitWidgetResponse(toolCallId, {\n error: reason || 'User cancelled the tool call',\n });\n },\n [submitWidgetResponse]\n );\n\n // Stop current conversation — calls the server-side stop endpoint\n // then stops polling and resets loading state.\n const stopChat = useCallback(async () => {\n const uid = chatUidRef.current;\n logRef.current.log('[useDevicChat] stopChat called, chatUid:', uid);\n if (clientRef.current && uid) {\n try {\n await clientRef.current.stopChat(assistantId, uid);\n logRef.current.log('[useDevicChat] stopChat API call succeeded');\n } catch (err) {\n logRef.current.warn('[useDevicChat] stopChat API call failed:', err);\n }\n }\n setShouldPoll(false);\n setIsLoading(false);\n setStatus('idle');\n }, [assistantId]);\n\n return {\n messages,\n chatUid,\n isLoading,\n status,\n error,\n limitExceeded,\n recalledMemories,\n handedOff,\n handedOffSubThreadId,\n sendMessage,\n clearChat,\n loadChat,\n onHandoffCompleted,\n stopChat,\n pendingWidgetCalls,\n submitWidgetResponse,\n cancelWidgetCall,\n };\n}\n"],"names":["useOptionalDevicContext","useMemo","resolvePollingInterval","createLogger","useRef","useState","useCallback","useEffect","DevicApiClient","useModelInterface","usePolling","DevicApiError"],"mappings":"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"}
package/dist/cjs/index.js CHANGED
@@ -20,6 +20,9 @@ require('react/jsx-runtime');
20
20
  require('react');
21
21
  var IntegrationLogo = require('./components/IntegrationsModal/IntegrationLogo.js');
22
22
  var useIntegrations = require('./components/IntegrationsModal/useIntegrations.js');
23
+ var McpServersSection = require('./components/IntegrationsModal/McpServersSection.js');
24
+ var McpConnectForm = require('./components/IntegrationsModal/McpConnectForm.js');
25
+ var useTenantMcp = require('./components/IntegrationsModal/useTenantMcp.js');
23
26
  var assistantInfo = require('./api/assistantInfo.js');
24
27
  var sharedSession = require('./provider/sharedSession.js');
25
28
  var theme = require('./components/theme.js');
@@ -63,6 +66,9 @@ exports.IntegrationsLauncher = IntegrationsLauncher.IntegrationsLauncher;
63
66
  exports.IntegrationsHint = IntegrationsHint.IntegrationsHint;
64
67
  exports.IntegrationLogo = IntegrationLogo.IntegrationLogo;
65
68
  exports.useIntegrations = useIntegrations.useIntegrations;
69
+ exports.McpServersSection = McpServersSection.McpServersSection;
70
+ exports.McpConnectForm = McpConnectForm.McpConnectForm;
71
+ exports.useTenantMcp = useTenantMcp.useTenantMcp;
66
72
  exports.forgetAssistant = assistantInfo.forgetAssistant;
67
73
  exports.useAssistantInfo = assistantInfo.useAssistantInfo;
68
74
  exports.createSharedSession = sharedSession.createSharedSession;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}