@darqlabs/curator-sdk-react 0.1.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 (76) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +205 -0
  3. package/dist/cjs/CuratorAdapter.d.ts +28 -0
  4. package/dist/cjs/CuratorAdapter.d.ts.map +1 -0
  5. package/dist/cjs/CuratorAdapter.js +100 -0
  6. package/dist/cjs/CuratorAdapter.js.map +1 -0
  7. package/dist/cjs/CuratorChat.d.ts +70 -0
  8. package/dist/cjs/CuratorChat.d.ts.map +1 -0
  9. package/dist/cjs/CuratorChat.js +454 -0
  10. package/dist/cjs/CuratorChat.js.map +1 -0
  11. package/dist/cjs/CuratorChatLauncher.d.ts +57 -0
  12. package/dist/cjs/CuratorChatLauncher.d.ts.map +1 -0
  13. package/dist/cjs/CuratorChatLauncher.js +134 -0
  14. package/dist/cjs/CuratorChatLauncher.js.map +1 -0
  15. package/dist/cjs/CuratorProvider.d.ts +37 -0
  16. package/dist/cjs/CuratorProvider.d.ts.map +1 -0
  17. package/dist/cjs/CuratorProvider.js +49 -0
  18. package/dist/cjs/CuratorProvider.js.map +1 -0
  19. package/dist/cjs/Markdown.d.ts +16 -0
  20. package/dist/cjs/Markdown.d.ts.map +1 -0
  21. package/dist/cjs/Markdown.js +18 -0
  22. package/dist/cjs/Markdown.js.map +1 -0
  23. package/dist/cjs/brand.d.ts +26 -0
  24. package/dist/cjs/brand.d.ts.map +1 -0
  25. package/dist/cjs/brand.js +47 -0
  26. package/dist/cjs/brand.js.map +1 -0
  27. package/dist/cjs/index.d.ts +10 -0
  28. package/dist/cjs/index.d.ts.map +1 -0
  29. package/dist/cjs/index.js +17 -0
  30. package/dist/cjs/index.js.map +1 -0
  31. package/dist/cjs/normalizeMarkdown.d.ts +24 -0
  32. package/dist/cjs/normalizeMarkdown.d.ts.map +1 -0
  33. package/dist/cjs/normalizeMarkdown.js +111 -0
  34. package/dist/cjs/normalizeMarkdown.js.map +1 -0
  35. package/dist/cjs/useCuratorChat.d.ts +79 -0
  36. package/dist/cjs/useCuratorChat.d.ts.map +1 -0
  37. package/dist/cjs/useCuratorChat.js +135 -0
  38. package/dist/cjs/useCuratorChat.js.map +1 -0
  39. package/dist/esm/CuratorAdapter.d.ts +28 -0
  40. package/dist/esm/CuratorAdapter.d.ts.map +1 -0
  41. package/dist/esm/CuratorAdapter.js +97 -0
  42. package/dist/esm/CuratorAdapter.js.map +1 -0
  43. package/dist/esm/CuratorChat.d.ts +70 -0
  44. package/dist/esm/CuratorChat.d.ts.map +1 -0
  45. package/dist/esm/CuratorChat.js +451 -0
  46. package/dist/esm/CuratorChat.js.map +1 -0
  47. package/dist/esm/CuratorChatLauncher.d.ts +57 -0
  48. package/dist/esm/CuratorChatLauncher.d.ts.map +1 -0
  49. package/dist/esm/CuratorChatLauncher.js +131 -0
  50. package/dist/esm/CuratorChatLauncher.js.map +1 -0
  51. package/dist/esm/CuratorProvider.d.ts +37 -0
  52. package/dist/esm/CuratorProvider.d.ts.map +1 -0
  53. package/dist/esm/CuratorProvider.js +44 -0
  54. package/dist/esm/CuratorProvider.js.map +1 -0
  55. package/dist/esm/Markdown.d.ts +16 -0
  56. package/dist/esm/Markdown.d.ts.map +1 -0
  57. package/dist/esm/Markdown.js +12 -0
  58. package/dist/esm/Markdown.js.map +1 -0
  59. package/dist/esm/brand.d.ts +26 -0
  60. package/dist/esm/brand.d.ts.map +1 -0
  61. package/dist/esm/brand.js +43 -0
  62. package/dist/esm/brand.js.map +1 -0
  63. package/dist/esm/index.d.ts +10 -0
  64. package/dist/esm/index.d.ts.map +1 -0
  65. package/dist/esm/index.js +6 -0
  66. package/dist/esm/index.js.map +1 -0
  67. package/dist/esm/normalizeMarkdown.d.ts +24 -0
  68. package/dist/esm/normalizeMarkdown.d.ts.map +1 -0
  69. package/dist/esm/normalizeMarkdown.js +108 -0
  70. package/dist/esm/normalizeMarkdown.js.map +1 -0
  71. package/dist/esm/package.json +3 -0
  72. package/dist/esm/useCuratorChat.d.ts +79 -0
  73. package/dist/esm/useCuratorChat.d.ts.map +1 -0
  74. package/dist/esm/useCuratorChat.js +132 -0
  75. package/dist/esm/useCuratorChat.js.map +1 -0
  76. package/package.json +66 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Darq Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # @darqlabs/curator-sdk-react
2
+
3
+ Official React components for Curator. Drop in a ready-to-use chat widget that talks to your deployed agents, or wire up your own UI with the headless hook.
4
+
5
+ Powered by [assistant-ui](https://github.com/Yonom/assistant-ui) internals — token-by-token streaming, edit/regenerate primitives, and tool-call extension points are available to consumers who want to go deeper than the drop-in widget.
6
+
7
+ ```tsx
8
+ // once, at the app root
9
+ import { Curator } from "@darqlabs/curator-sdk"
10
+ import { CuratorProvider } from "@darqlabs/curator-sdk-react"
11
+
12
+ const curator = new Curator({
13
+ apiKey: "CURATOR_API_KEY",
14
+ project: "default",
15
+ environment: "production",
16
+ })
17
+
18
+ export function App() {
19
+ return (
20
+ <CuratorProvider client={curator}>
21
+ <Routes />
22
+ </CuratorProvider>
23
+ )
24
+ }
25
+
26
+ // anywhere inside
27
+ import { CuratorChat } from "@darqlabs/curator-sdk-react"
28
+
29
+ export function Support() {
30
+ return <CuratorChat agent="support-bot" />
31
+ }
32
+ ```
33
+
34
+ ## Install
35
+
36
+ ```bash
37
+ npm install @darqlabs/curator-sdk @darqlabs/curator-sdk-react
38
+ ```
39
+
40
+ React 18 or 19. Works with Vite, Next.js, Remix, anything with `react` and `react-dom`.
41
+
42
+ ## Why pass the client?
43
+
44
+ The components consume a `Curator` instance (built from `@darqlabs/curator-sdk`) rather than an API key. That keeps auth, project / environment defaults, custom fetch, and headers in one place — the same instance can power multiple chats, file uploads, or your own SDK calls.
45
+
46
+ Wrap your tree once with `<CuratorProvider>` and components further down read the client from context automatically. Or pass `curator` explicitly to override (e.g. when one screen needs to talk to a different client).
47
+
48
+ ## Drop-in component
49
+
50
+ ```tsx
51
+ <CuratorChat
52
+ agent="support-bot"
53
+ // optional — overrides the provider's client
54
+ curator={otherCurator}
55
+ // optional UX
56
+ title="Support"
57
+ placeholder="Ask anything…"
58
+ welcomeMessage="Hi! How can I help?"
59
+ // optional locator overrides
60
+ project="default"
61
+ environment="production"
62
+ conversationId={savedConversationId}
63
+ // optional message actions (both default off)
64
+ enableRetry // ↻ regenerate button under the latest assistant reply
65
+ enableCopy // copy button on assistant messages
66
+ // optional styling
67
+ theme="light" // or "dark"
68
+ className="my-chat"
69
+ style={{ height: 520 }}
70
+ // optional events
71
+ onMessage={(msg) => console.log(msg)}
72
+ onError={(err) => console.error(err)}
73
+ />
74
+ ```
75
+
76
+ ### Message actions
77
+
78
+ | Prop | Default | Effect |
79
+ | --- | --- | --- |
80
+ | `enableRetry` | `false` | Shows a ↻ button under the latest assistant message that re-sends the preceding user turn. |
81
+ | `enableCopy` | `false` | Shows a copy button on assistant messages (with a brief check-mark confirmation). |
82
+
83
+ ### Theming
84
+
85
+ Two built-in palettes via the `theme` prop (`"light"` / `"dark"`). For finer control, override the design-token CSS variables through the **`style` prop**:
86
+
87
+ ```tsx
88
+ <CuratorChat
89
+ agent="support-bot"
90
+ style={{
91
+ ["--curator-accent"]: "#2563eb", // agent bubble + send button background
92
+ ["--curator-accent-text"]: "#ffffff", // agent bubble + send button text/icon
93
+ ["--curator-user-bubble"]: "#f1f5f9", // user bubble background
94
+ ["--curator-bg"]: "#fafafa", // chat background
95
+ ["--curator-text"]: "#18181b", // primary text
96
+ ["--curator-muted"]: "#71717a", // action icons, timestamps, hints
97
+ ["--curator-border"]: "rgba(0,0,0,0.08)",
98
+ ["--curator-error"]: "#b91c1c",
99
+ ["--curator-radius"]: "16px", // container corner radius
100
+ } as React.CSSProperties}
101
+ />
102
+ ```
103
+
104
+ | Token | Controls |
105
+ | --- | --- |
106
+ | `--curator-accent` / `--curator-accent-text` | Agent (assistant) bubble **and** the send button |
107
+ | `--curator-user-bubble` | User bubble background (text uses `--curator-text`) |
108
+ | `--curator-bg` / `--curator-surface` | Chat background / composer + input background |
109
+ | `--curator-muted` | Action icons, welcome text, timestamps |
110
+ | `--curator-border`, `--curator-error`, `--curator-radius` | Borders, error text, container radius |
111
+
112
+ Use the **`style` prop** (not a CSS class or an ancestor rule): the widget sets these variables inline on its own root for the active `theme`, and inline styles win over a class — the `style` prop is applied last, so it's the one override that reliably takes effect. The widget ships no external stylesheet.
113
+
114
+ ## Floating launcher
115
+
116
+ For a chat-bubble-in-the-corner widget instead of an inline panel, use `<CuratorChatLauncher />`. Same props as `<CuratorChat />` plus placement controls:
117
+
118
+ ```tsx
119
+ import { CuratorChatLauncher } from "@darqlabs/curator-sdk-react"
120
+
121
+ <CuratorChatLauncher
122
+ agent="support-bot"
123
+ placement="bottom-right" // or bottom-left / top-right / top-left
124
+ offset={24} // px from the docked corner
125
+ panelWidth={380}
126
+ panelHeight={560}
127
+ defaultOpen={false}
128
+ // all <CuratorChat /> props are forwarded:
129
+ title="Support"
130
+ theme="light"
131
+ welcomeMessage="Hi! How can I help?"
132
+ />
133
+ ```
134
+
135
+ Renders via a portal to `document.body`, so it escapes stacking contexts in the host app. ESC closes the panel; clicking outside doesn't (intentional — keeps chat state from getting lost on a stray click).
136
+
137
+ ## Headless hook
138
+
139
+ For full UI control, use `useCuratorChat` directly. `curator` is optional when a `<CuratorProvider>` is in scope:
140
+
141
+ ```tsx
142
+ import { useCuratorChat } from "@darqlabs/curator-sdk-react"
143
+
144
+ function MyChat() {
145
+ const { messages, send, sending, error, conversationId } = useCuratorChat({
146
+ agent: "support-bot",
147
+ })
148
+
149
+ return (
150
+ <div>
151
+ {messages.map((m) =>
152
+ m.kind === "user" ? <UserBubble key={m.localId} text={m.content} />
153
+ : m.kind === "assistant" ? <BotBubble key={m.runId} text={m.content} />
154
+ : <ErrorRow key={m.localId} text={m.message} />,
155
+ )}
156
+ {sending && <Typing />}
157
+ <Composer onSubmit={(text) => send(text)} />
158
+ </div>
159
+ )
160
+ }
161
+ ```
162
+
163
+ The hook returns:
164
+
165
+ | | |
166
+ | --- | --- |
167
+ | `messages` | Chronological list of bubbles (`user` / `assistant` / `error`). |
168
+ | `send(content, opts?)` | Append a user message and await the assistant's reply. `opts.files` for attachments, `opts.timeoutMs` to override the wait. |
169
+ | `sending` | True while a `send` is in flight. |
170
+ | `error` | Most recent error, or null. Cleared on next successful send. |
171
+ | `chat` | Underlying SDK `Chat` instance. |
172
+ | `conversationId` | Conversation id once one has been created. |
173
+ | `reset()` | Clear visible messages (keeps the same conversation). |
174
+
175
+ ## Reading the client directly
176
+
177
+ ```tsx
178
+ import { useCurator } from "@darqlabs/curator-sdk-react"
179
+
180
+ function UploadButton() {
181
+ const curator = useCurator()
182
+ return (
183
+ <button onClick={async () => {
184
+ const fileRef = await curator.files.upload({ filename, mimeType, data })
185
+ // …
186
+ }}>
187
+ Upload
188
+ </button>
189
+ )
190
+ }
191
+ ```
192
+
193
+ Throws a clear error if no `<CuratorProvider>` is mounted higher in the tree.
194
+
195
+ ## Errors
196
+
197
+ The hook captures all SDK errors into a friendly `kind: "error"` bubble — auth, agent failures, timeouts, approval-required pauses, etc. — and also exposes the raw error via `error` and the `onError` prop so you can log or surface them however you like.
198
+
199
+ ## Security in the browser
200
+
201
+ The chat runs wherever your `Curator` client runs. If you instantiate the client in browser code, the API key ships in your bundle. Recommended patterns:
202
+
203
+ 1. **Backend proxy.** Run the SDK on your server; have your frontend call your server. Your server holds the key.
204
+ 2. **Trusted internal tools.** Employee dashboards behind SSO are usually fine.
205
+ 3. **Server-issued tokens.** Not supported yet — reach out if you need them.
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Adapter that plugs the Curator SDK into assistant-ui's `useLocalRuntime`.
3
+ *
4
+ * Each invocation of `run()` is one user-turn. We pull the latest user
5
+ * message text out of assistant-ui's structured `messages[]`, hand it to
6
+ * `chat.stream(...)`, and yield assistant-ui-shaped updates back as the
7
+ * SDK's stream events flow in.
8
+ *
9
+ * stream.delta → accumulate text, yield partial assistant content
10
+ * stream.done → yield final content + status: complete
11
+ * stream.error → yield friendly text + status: incomplete
12
+ * stream.paused_for_ → yield "contact your administrator" text +
13
+ * approval status: incomplete
14
+ *
15
+ * The Chat handle is constructed once per chat session (one per
16
+ * mounted CuratorChat / launcher panel) so multi-turn context stays
17
+ * intact across runs.
18
+ */
19
+ import type { ChatModelAdapter } from "@assistant-ui/react";
20
+ import type { AssistantMessage, Chat, CuratorError } from "@darqlabs/curator-sdk";
21
+ export interface CuratorAdapterCallbacks {
22
+ /** Fired once per successfully-returned assistant message. */
23
+ onMessage?: (message: AssistantMessage) => void;
24
+ /** Fired on any send-time error surfaced through the stream. */
25
+ onError?: (error: CuratorError | Error) => void;
26
+ }
27
+ export declare function createCuratorAdapter(chat: Chat, callbacks?: CuratorAdapterCallbacks): ChatModelAdapter;
28
+ //# sourceMappingURL=CuratorAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorAdapter.d.ts","sourceRoot":"","sources":["../../src/CuratorAdapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAsB,MAAM,qBAAqB,CAAA;AAC/E,OAAO,KAAK,EACV,gBAAgB,EAChB,IAAI,EACJ,YAAY,EACb,MAAM,uBAAuB,CAAA;AAE9B,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC/C,gEAAgE;IAChE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,KAAK,IAAI,CAAA;CAChD;AAED,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,IAAI,EACV,SAAS,GAAE,uBAA4B,GACtC,gBAAgB,CA6DlB"}
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ /**
3
+ * Adapter that plugs the Curator SDK into assistant-ui's `useLocalRuntime`.
4
+ *
5
+ * Each invocation of `run()` is one user-turn. We pull the latest user
6
+ * message text out of assistant-ui's structured `messages[]`, hand it to
7
+ * `chat.stream(...)`, and yield assistant-ui-shaped updates back as the
8
+ * SDK's stream events flow in.
9
+ *
10
+ * stream.delta → accumulate text, yield partial assistant content
11
+ * stream.done → yield final content + status: complete
12
+ * stream.error → yield friendly text + status: incomplete
13
+ * stream.paused_for_ → yield "contact your administrator" text +
14
+ * approval status: incomplete
15
+ *
16
+ * The Chat handle is constructed once per chat session (one per
17
+ * mounted CuratorChat / launcher panel) so multi-turn context stays
18
+ * intact across runs.
19
+ */
20
+ Object.defineProperty(exports, "__esModule", { value: true });
21
+ exports.createCuratorAdapter = createCuratorAdapter;
22
+ function createCuratorAdapter(chat, callbacks = {}) {
23
+ return {
24
+ async *run({ messages, abortSignal }) {
25
+ const userText = extractLatestUserText(messages);
26
+ if (!userText)
27
+ return;
28
+ let acc = "";
29
+ try {
30
+ for await (const event of chat.stream(userText)) {
31
+ if (abortSignal.aborted)
32
+ return;
33
+ if (event.type === "delta") {
34
+ acc += event.text;
35
+ yield { content: [{ type: "text", text: acc }] };
36
+ continue;
37
+ }
38
+ if (event.type === "done") {
39
+ const finalText = event.message?.content ?? acc;
40
+ yield {
41
+ content: [{ type: "text", text: finalText }],
42
+ status: { type: "complete", reason: "stop" },
43
+ };
44
+ if (event.message)
45
+ callbacks.onMessage?.(event.message);
46
+ return;
47
+ }
48
+ if (event.type === "error") {
49
+ yield {
50
+ content: [{ type: "text", text: event.message }],
51
+ status: { type: "incomplete", reason: "error" },
52
+ };
53
+ callbacks.onError?.(new Error(event.message));
54
+ return;
55
+ }
56
+ if (event.type === "paused_for_approval") {
57
+ const pausedMessage = `This action needs administrator approval. ` +
58
+ `Contact your administrator to review the request for "${event.approval.tool_name}".`;
59
+ yield {
60
+ content: [{ type: "text", text: pausedMessage }],
61
+ status: { type: "incomplete", reason: "error" },
62
+ };
63
+ callbacks.onError?.(new Error(pausedMessage));
64
+ return;
65
+ }
66
+ // tool_call.* and any future event types are silently dropped
67
+ // until a richer UI surface ships for them.
68
+ }
69
+ }
70
+ catch (err) {
71
+ const message = err?.message || "Something went wrong sending your message.";
72
+ yield {
73
+ content: [{ type: "text", text: message }],
74
+ status: { type: "incomplete", reason: "error" },
75
+ };
76
+ callbacks.onError?.(err);
77
+ }
78
+ },
79
+ };
80
+ }
81
+ /**
82
+ * Pull the latest user-turn text out of assistant-ui's structured
83
+ * message array. Text parts are concatenated with newlines; other
84
+ * part types (image, file, etc.) are ignored for now — the SDK's
85
+ * `chat.stream` accepts plain text content only.
86
+ */
87
+ function extractLatestUserText(messages) {
88
+ for (let i = messages.length - 1; i >= 0; i--) {
89
+ const m = messages[i];
90
+ if (m.role !== "user")
91
+ continue;
92
+ const text = m.content
93
+ .filter((p) => typeof p === "object" && p !== null && p.type === "text")
94
+ .map((p) => p.text)
95
+ .join("\n");
96
+ return text.trim();
97
+ }
98
+ return "";
99
+ }
100
+ //# sourceMappingURL=CuratorAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorAdapter.js","sourceRoot":"","sources":["../../src/CuratorAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * <CuratorChat /> — drop-in chat widget backed by a Curator SDK client.
3
+ *
4
+ * <CuratorChat curator={curator} agent="support-bot" />
5
+ *
6
+ * Internals are powered by `@assistant-ui/react` — `useLocalRuntime`
7
+ * wraps our `CuratorAdapter`, which delegates each user turn to
8
+ * `chat.stream(...)` for token-by-token rendering. The outer chrome
9
+ * (header, brand footer, theme tokens, close button) and the bubble
10
+ * layout stay ours so the widget keeps its identity across themes.
11
+ */
12
+ import { type CSSProperties, type ReactNode } from "react";
13
+ import type { AssistantMessage, Curator, CuratorError, Environment } from "@darqlabs/curator-sdk";
14
+ export interface CuratorChatProps {
15
+ /** SDK instance. Optional when a `<CuratorProvider>` is mounted. */
16
+ curator?: Curator;
17
+ /** Deployment slug to chat with. */
18
+ agent: string;
19
+ /** Override the SDK's default project for this widget. */
20
+ project?: string;
21
+ /** Override the SDK's default environment for this widget. */
22
+ environment?: Environment;
23
+ /** Address a system-scoped deployment. */
24
+ system?: boolean;
25
+ /** Reattach to an existing conversation id instead of starting fresh. */
26
+ conversationId?: string;
27
+ /** Header title. Default: "Chat". */
28
+ title?: string;
29
+ /** Input placeholder. Default: "Type a message…". */
30
+ placeholder?: string;
31
+ /** Shown above the empty message list as a system prompt. */
32
+ welcomeMessage?: string;
33
+ /** Built-in palette. Default: "light". */
34
+ theme?: "light" | "dark";
35
+ /** Class applied to the outer wrapper. */
36
+ className?: string;
37
+ /** Inline styles merged onto the outer wrapper. */
38
+ style?: CSSProperties;
39
+ /** If set, the header shows an X button that calls this. */
40
+ onClose?: () => void;
41
+ /**
42
+ * Indicator rendered inside the assistant bubble while it's waiting
43
+ * for the first token (the gap between Send and the first delta).
44
+ * Default: animated three-dot pulse. Pass any node to swap it out.
45
+ */
46
+ loadingIndicator?: ReactNode;
47
+ /** Fired once per assistant message that completes successfully. */
48
+ onMessage?: (message: AssistantMessage) => void;
49
+ /** Fired on any terminal stream error or thrown exception. */
50
+ onError?: (error: CuratorError | Error) => void;
51
+ /**
52
+ * Show a retry (↻) button under the latest assistant message. Default:
53
+ * off. Retry re-sends the preceding user message through the SDK — note
54
+ * that this appends a fresh turn to the server-side conversation rather
55
+ * than regenerating the last reply in place, so persisted history will
56
+ * contain the duplicated user message. Fine for casual / demo widgets;
57
+ * enable only if that history shape is acceptable for your deployment.
58
+ */
59
+ enableRetry?: boolean;
60
+ /**
61
+ * Show a copy button on assistant messages that copies the message text
62
+ * to the clipboard. Default: off. Appears alongside retry (when enabled)
63
+ * in the per-message action bar; a check glyph confirms the copy briefly.
64
+ */
65
+ enableCopy?: boolean;
66
+ }
67
+ export declare function CuratorChat(props: CuratorChatProps): import("react").JSX.Element;
68
+ declare function AssistantMessage(): import("react").JSX.Element;
69
+ export {};
70
+ //# sourceMappingURL=CuratorChat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CuratorChat.d.ts","sourceRoot":"","sources":["../../src/CuratorChat.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAML,KAAK,aAAa,EAClB,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AAUd,OAAO,KAAK,EACV,gBAAgB,EAEhB,OAAO,EACP,YAAY,EACZ,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAM9B,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB,0CAA0C;IAC1C,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE,aAAa,CAAA;IAErB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IAEpB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,oEAAoE;IACpE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC/C,8DAA8D;IAC9D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,GAAG,KAAK,KAAK,IAAI,CAAA;IAE/C;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,+BAqGlD;AAoDD,iBAAS,gBAAgB,gCAqCxB"}