@aganzefelicite/responsekit-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.
- package/README.md +87 -0
- package/dist/ChartRenderer-UJNU2VNH.cjs +153 -0
- package/dist/ChartRenderer-UJNU2VNH.cjs.map +1 -0
- package/dist/ChartRenderer-URPZESVN.js +151 -0
- package/dist/ChartRenderer-URPZESVN.js.map +1 -0
- package/dist/chunk-3FSZRQQU.js +33 -0
- package/dist/chunk-3FSZRQQU.js.map +1 -0
- package/dist/chunk-D4WIPDH3.cjs +38 -0
- package/dist/chunk-D4WIPDH3.cjs.map +1 -0
- package/dist/index.cjs +5053 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +313 -0
- package/dist/index.d.ts +313 -0
- package/dist/index.js +4980 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +108 -0
- package/package.json +53 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentType, ReactNode, Component, ErrorInfo } from 'react';
|
|
3
|
+
import { Block, AiResponse, AiStreamState, ConversationSummary, MessageResponse, TextBlock as TextBlock$1, KpiBlock as KpiBlock$1, ChartBlock as ChartBlock$1, TableBlock as TableBlock$1, InsightBlock as InsightBlock$1, RecommendationBlock as RecommendationBlock$1, FilterBlock as FilterBlock$1, SseEvent } from '@responsekit/schema';
|
|
4
|
+
export * from '@responsekit/schema';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Actions are the SDK's single outbound channel. Blocks and custom components emit
|
|
8
|
+
* actions; the host app decides what they mean. The SDK NEVER runs business logic —
|
|
9
|
+
* it only forwards intent via `onAction`.
|
|
10
|
+
*/
|
|
11
|
+
interface DownloadAction {
|
|
12
|
+
type: "DOWNLOAD";
|
|
13
|
+
/** What to download — e.g. a table's rows, a chart's data, or a server-side artifact id. */
|
|
14
|
+
format?: "CSV" | "JSON" | string;
|
|
15
|
+
filename?: string;
|
|
16
|
+
data?: unknown;
|
|
17
|
+
/** The block that originated the action, when applicable. */
|
|
18
|
+
blockId?: string;
|
|
19
|
+
}
|
|
20
|
+
interface OpenLinkAction {
|
|
21
|
+
type: "OPEN_LINK";
|
|
22
|
+
href: string;
|
|
23
|
+
target?: "_blank" | "_self";
|
|
24
|
+
blockId?: string;
|
|
25
|
+
}
|
|
26
|
+
interface RefreshAction {
|
|
27
|
+
type: "REFRESH";
|
|
28
|
+
responseId?: string;
|
|
29
|
+
}
|
|
30
|
+
interface CustomAction {
|
|
31
|
+
type: "CUSTOM";
|
|
32
|
+
/** A host-defined action name, e.g. "DRILL_DOWN". */
|
|
33
|
+
name: string;
|
|
34
|
+
payload?: unknown;
|
|
35
|
+
blockId?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Open union: the known actions plus an escape hatch for host- or plugin-defined ones.
|
|
39
|
+
* Consumers can narrow on `action.type`.
|
|
40
|
+
*/
|
|
41
|
+
type AiAction = DownloadAction | OpenLinkAction | RefreshAction | CustomAction | ({
|
|
42
|
+
type: string;
|
|
43
|
+
} & Record<string, unknown>);
|
|
44
|
+
type OnAction = (action: AiAction) => void;
|
|
45
|
+
/** A no-op default so components can always call `onAction` safely. */
|
|
46
|
+
declare const noopAction: OnAction;
|
|
47
|
+
|
|
48
|
+
/** Props every block component receives. */
|
|
49
|
+
interface BlockComponentProps<B extends Block = Block> {
|
|
50
|
+
block: B;
|
|
51
|
+
onAction: OnAction;
|
|
52
|
+
}
|
|
53
|
+
type BlockComponent<B extends Block = Block> = ComponentType<BlockComponentProps<B>>;
|
|
54
|
+
/**
|
|
55
|
+
* Override map passed to `<AiRenderer components={...} />`. Keys are block `type`
|
|
56
|
+
* strings; values replace the default component for that type. Custom (non-builtin)
|
|
57
|
+
* types are allowed too.
|
|
58
|
+
*/
|
|
59
|
+
type BlockComponents = Record<string, BlockComponent>;
|
|
60
|
+
|
|
61
|
+
interface AiRendererProps {
|
|
62
|
+
/** A complete response object (typically from `useAiStream().response`). */
|
|
63
|
+
response: AiResponse;
|
|
64
|
+
/** Per-render component overrides, keyed by block `type`. */
|
|
65
|
+
components?: BlockComponents;
|
|
66
|
+
/** Single outbound action channel. */
|
|
67
|
+
onAction?: OnAction;
|
|
68
|
+
className?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Renders a complete `AiResponse`. Switches on `response.type`:
|
|
72
|
+
* - TEXT → Markdown (when `format === "MARKDOWN"`) or plain text
|
|
73
|
+
* - ANALYTICS → optional title, then each block via the registry, in order
|
|
74
|
+
* - ERROR → error component
|
|
75
|
+
*
|
|
76
|
+
* Every block is wrapped in an error boundary and resolved through the registry, so
|
|
77
|
+
* unknown types or render failures degrade to a fallback rather than crashing.
|
|
78
|
+
*/
|
|
79
|
+
declare function AiRenderer({ response, components, onAction, className, }: AiRendererProps): react.JSX.Element;
|
|
80
|
+
declare function ErrorView({ message }: {
|
|
81
|
+
message: string;
|
|
82
|
+
}): react.JSX.Element;
|
|
83
|
+
|
|
84
|
+
interface UseAiStreamOptions {
|
|
85
|
+
baseUrl: string;
|
|
86
|
+
conversationId: string;
|
|
87
|
+
message: string;
|
|
88
|
+
headers?: Record<string, string>;
|
|
89
|
+
fetchImpl?: typeof fetch;
|
|
90
|
+
/**
|
|
91
|
+
* Auto-start the stream when `message` (and the endpoint) are set. Default true.
|
|
92
|
+
* Set false to control start/stop manually via the returned `start()`/`stop()`.
|
|
93
|
+
*/
|
|
94
|
+
enabled?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface UseAiStreamResult extends AiStreamState {
|
|
97
|
+
isStreaming: boolean;
|
|
98
|
+
/** (Re)start the stream. Aborts any in-flight stream first. */
|
|
99
|
+
start: () => void;
|
|
100
|
+
/** Abort the in-flight stream. */
|
|
101
|
+
stop: () => void;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Consume the SSE message stream and reduce its events into live `AiStreamState`.
|
|
105
|
+
* The response is assembled incrementally (blocks appended as they arrive).
|
|
106
|
+
*/
|
|
107
|
+
declare function useAiStream(options: UseAiStreamOptions): UseAiStreamResult;
|
|
108
|
+
|
|
109
|
+
interface AiStreamProps extends UseAiStreamOptions {
|
|
110
|
+
components?: BlockComponents;
|
|
111
|
+
onAction?: OnAction;
|
|
112
|
+
className?: string;
|
|
113
|
+
/** Custom loading UI. Receives the live progress state. */
|
|
114
|
+
renderLoading?: (state: AiStreamState) => ReactNode;
|
|
115
|
+
/** Custom error UI. */
|
|
116
|
+
renderError?: (error: string) => ReactNode;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* End-to-end: streams from `POST {baseUrl}/api/conversations/{id}/messages`, shows a
|
|
120
|
+
* progress-driven loading state, then renders the assembled response with `AiRenderer`.
|
|
121
|
+
*
|
|
122
|
+
* As soon as any response content exists it is rendered live (blocks appear in order);
|
|
123
|
+
* the loading indicator stays visible until the stream finishes.
|
|
124
|
+
*/
|
|
125
|
+
declare function AiStream({ components, onAction, className, renderLoading, renderError, ...streamOptions }: AiStreamProps): react.JSX.Element;
|
|
126
|
+
|
|
127
|
+
/** One user turn plus the assistant's (streaming or finished) response state. */
|
|
128
|
+
interface ChatTurn {
|
|
129
|
+
id: string;
|
|
130
|
+
userMessage: string;
|
|
131
|
+
/** Live stream state for this turn; `state.response` is the assembled AiResponse. */
|
|
132
|
+
state: AiStreamState;
|
|
133
|
+
}
|
|
134
|
+
interface UseChatOptions {
|
|
135
|
+
baseUrl: string;
|
|
136
|
+
/**
|
|
137
|
+
* Use an existing conversation. If omitted, a conversation is created lazily on the
|
|
138
|
+
* first `send()` (via POST /api/conversations).
|
|
139
|
+
*/
|
|
140
|
+
conversationId?: string;
|
|
141
|
+
/** Title for the auto-created conversation. Defaults to the first message (truncated). */
|
|
142
|
+
titleFor?: (firstMessage: string) => string;
|
|
143
|
+
headers?: Record<string, string>;
|
|
144
|
+
fetchImpl?: typeof fetch;
|
|
145
|
+
}
|
|
146
|
+
interface UseChatResult {
|
|
147
|
+
conversationId?: string;
|
|
148
|
+
turns: ChatTurn[];
|
|
149
|
+
isStreaming: boolean;
|
|
150
|
+
error?: string;
|
|
151
|
+
/** Send a message. Creates the conversation first if needed. */
|
|
152
|
+
send: (message: string) => Promise<void>;
|
|
153
|
+
/** Abort the in-flight stream (if any). */
|
|
154
|
+
stop: () => void;
|
|
155
|
+
/** Clear all turns (keeps the conversation id). */
|
|
156
|
+
reset: () => void;
|
|
157
|
+
/** Start a brand-new conversation: clears turns and drops the id so the next
|
|
158
|
+
* `send()` creates a fresh conversation. */
|
|
159
|
+
newConversation: () => void;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Drive a multi-message conversation: one conversation id, an ordered list of turns,
|
|
163
|
+
* each assistant response assembled incrementally from the SSE stream. Built directly
|
|
164
|
+
* on `streamMessage` + `streamReducer` so it stays a thin, predictable layer.
|
|
165
|
+
*/
|
|
166
|
+
declare function useChat(options: UseChatOptions): UseChatResult;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Framework-agnostic REST client for the conversation lifecycle.
|
|
170
|
+
*
|
|
171
|
+
* The SDK's core job is message → render, but hosts still need to create/list/rename
|
|
172
|
+
* conversations. These are thin, dependency-free `fetch` wrappers over the backend's
|
|
173
|
+
* plain REST endpoints, kept optional so the render path stays lean. (Lives next to
|
|
174
|
+
* `streamMessage`; both are UI-agnostic and could move to a `core` package later.)
|
|
175
|
+
*/
|
|
176
|
+
interface ConversationClientOptions {
|
|
177
|
+
baseUrl: string;
|
|
178
|
+
/** Extra headers (e.g. Authorization) merged onto every request. */
|
|
179
|
+
headers?: Record<string, string>;
|
|
180
|
+
signal?: AbortSignal;
|
|
181
|
+
/** Injectable fetch (tests / non-browser runtimes). Defaults to global `fetch`. */
|
|
182
|
+
fetchImpl?: typeof fetch;
|
|
183
|
+
}
|
|
184
|
+
/** POST /api/conversations — create a conversation. */
|
|
185
|
+
declare function createConversation(opts: ConversationClientOptions & {
|
|
186
|
+
title?: string;
|
|
187
|
+
}): Promise<ConversationSummary>;
|
|
188
|
+
/** GET /api/conversations — list conversations. */
|
|
189
|
+
declare function listConversations(opts: ConversationClientOptions): Promise<ConversationSummary[]>;
|
|
190
|
+
/** GET /api/conversations/{id} — fetch one conversation. */
|
|
191
|
+
declare function getConversation(opts: ConversationClientOptions & {
|
|
192
|
+
conversationId: string;
|
|
193
|
+
}): Promise<ConversationSummary>;
|
|
194
|
+
/** PATCH /api/conversations/{id} — rename a conversation. */
|
|
195
|
+
declare function renameConversation(opts: ConversationClientOptions & {
|
|
196
|
+
conversationId: string;
|
|
197
|
+
title: string;
|
|
198
|
+
}): Promise<ConversationSummary>;
|
|
199
|
+
/** DELETE /api/conversations/{id}. */
|
|
200
|
+
declare function deleteConversation(opts: ConversationClientOptions & {
|
|
201
|
+
conversationId: string;
|
|
202
|
+
}): Promise<void>;
|
|
203
|
+
/** GET /api/conversations/{id}/messages — load prior messages (history). */
|
|
204
|
+
declare function getMessages(opts: ConversationClientOptions & {
|
|
205
|
+
conversationId: string;
|
|
206
|
+
}): Promise<MessageResponse[]>;
|
|
207
|
+
|
|
208
|
+
interface RegisterBlockOptions {
|
|
209
|
+
type: string;
|
|
210
|
+
component: BlockComponent;
|
|
211
|
+
/** When false, does not replace an existing global registration. Default true. */
|
|
212
|
+
override?: boolean;
|
|
213
|
+
}
|
|
214
|
+
/** Register a custom/unknown block type globally (extension point). */
|
|
215
|
+
declare function registerBlock(options: RegisterBlockOptions): void;
|
|
216
|
+
/** Remove a global registration (mainly for tests/cleanup). */
|
|
217
|
+
declare function unregisterBlock(type: string): void;
|
|
218
|
+
/** Snapshot of globally registered types. */
|
|
219
|
+
declare function registeredBlockTypes(): string[];
|
|
220
|
+
/**
|
|
221
|
+
* Resolve the component for a block type. Always returns a component — never null —
|
|
222
|
+
* falling back to `FallbackBlock` so rendering can never crash on an unknown type.
|
|
223
|
+
*/
|
|
224
|
+
declare function resolveBlockComponent(type: string, overrides?: BlockComponents): BlockComponent;
|
|
225
|
+
|
|
226
|
+
/** A block-level TEXT node. Rendered as (safe) Markdown. */
|
|
227
|
+
declare function TextBlock({ block }: BlockComponentProps<TextBlock$1>): react.JSX.Element;
|
|
228
|
+
|
|
229
|
+
declare function KpiBlock({ block }: BlockComponentProps<KpiBlock$1>): react.JSX.Element;
|
|
230
|
+
|
|
231
|
+
declare function ChartBlock({ block }: BlockComponentProps<ChartBlock$1>): react.JSX.Element;
|
|
232
|
+
|
|
233
|
+
declare function TableBlock({ block, onAction }: BlockComponentProps<TableBlock$1>): react.JSX.Element;
|
|
234
|
+
|
|
235
|
+
declare function InsightBlock({ block }: BlockComponentProps<InsightBlock$1>): react.JSX.Element;
|
|
236
|
+
|
|
237
|
+
declare function RecommendationBlock({ block, }: BlockComponentProps<RecommendationBlock$1>): react.JSX.Element;
|
|
238
|
+
|
|
239
|
+
declare function FilterBlock({ block }: BlockComponentProps<FilterBlock$1>): react.JSX.Element;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The graceful catch-all. Rendered for unknown block types, or known types whose
|
|
243
|
+
* required fields were missing/invalid (the parser coerces those to UnknownBlock).
|
|
244
|
+
* Never throws; optionally shows the raw payload in dev to aid debugging.
|
|
245
|
+
*/
|
|
246
|
+
declare function FallbackBlock({ block }: BlockComponentProps<Block>): react.JSX.Element;
|
|
247
|
+
|
|
248
|
+
/** The built-in block components, keyed by block `type`. */
|
|
249
|
+
declare const defaultBlockComponents: BlockComponents;
|
|
250
|
+
|
|
251
|
+
interface MarkdownProps {
|
|
252
|
+
children: string;
|
|
253
|
+
className?: string;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Renders AI-authored Markdown safely.
|
|
257
|
+
*
|
|
258
|
+
* Security posture (see the prompt's non-negotiables):
|
|
259
|
+
* - GitHub-flavored Markdown via `remark-gfm`.
|
|
260
|
+
* - NO `rehype-raw`: raw HTML in the source is treated as text, never parsed/injected.
|
|
261
|
+
* - `react-markdown` builds a React tree — no `dangerouslySetInnerHTML` anywhere.
|
|
262
|
+
* - URLs are passed through react-markdown's default transform, which strips
|
|
263
|
+
* dangerous protocols (javascript:, data:, etc.). Links open in a new tab with
|
|
264
|
+
* `rel="noopener noreferrer"`.
|
|
265
|
+
*/
|
|
266
|
+
declare function Markdown({ children, className }: MarkdownProps): react.JSX.Element;
|
|
267
|
+
|
|
268
|
+
interface Props {
|
|
269
|
+
children: ReactNode;
|
|
270
|
+
fallback: (error: Error) => ReactNode;
|
|
271
|
+
onError?: (error: Error, info: ErrorInfo) => void;
|
|
272
|
+
}
|
|
273
|
+
interface State {
|
|
274
|
+
error: Error | null;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Catches render-time errors from a single block/subtree so one bad custom component
|
|
278
|
+
* (or an unexpected data shape) can degrade to a fallback instead of taking down the
|
|
279
|
+
* whole host app. This backs the "never crash" guarantee at the render layer, on top
|
|
280
|
+
* of the schema-level validation.
|
|
281
|
+
*/
|
|
282
|
+
declare class ErrorBoundary extends Component<Props, State> {
|
|
283
|
+
state: State;
|
|
284
|
+
static getDerivedStateFromError(error: Error): State;
|
|
285
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
286
|
+
render(): ReactNode;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* SSE transport. The message endpoint is POST and streams `text/event-stream`, so the
|
|
291
|
+
* native `EventSource` (GET-only) cannot be used — we drive `fetch` + `ReadableStream`
|
|
292
|
+
* and parse the SSE framing by hand.
|
|
293
|
+
*/
|
|
294
|
+
interface StreamMessageOptions {
|
|
295
|
+
baseUrl: string;
|
|
296
|
+
conversationId: string;
|
|
297
|
+
message: string;
|
|
298
|
+
/** Extra headers (e.g. Authorization) merged onto the request. */
|
|
299
|
+
headers?: Record<string, string>;
|
|
300
|
+
signal?: AbortSignal;
|
|
301
|
+
/** Injectable fetch (tests / non-browser runtimes). Defaults to global `fetch`. */
|
|
302
|
+
fetchImpl?: typeof fetch;
|
|
303
|
+
}
|
|
304
|
+
/** Build the POST message URL for a conversation. */
|
|
305
|
+
declare function messageUrl(baseUrl: string, conversationId: string): string;
|
|
306
|
+
/**
|
|
307
|
+
* Open the stream and yield typed `SseEvent`s as they arrive. Never throws for
|
|
308
|
+
* transport/parse problems — it yields a terminal `error` event instead, so the
|
|
309
|
+
* reducer/host always sees a clean signal.
|
|
310
|
+
*/
|
|
311
|
+
declare function streamMessage(options: StreamMessageOptions): AsyncGenerator<SseEvent>;
|
|
312
|
+
|
|
313
|
+
export { type AiAction, AiRenderer, type AiRendererProps, AiStream, type AiStreamProps, type BlockComponent, type BlockComponentProps, type BlockComponents, ChartBlock, type ChatTurn, type ConversationClientOptions, type CustomAction, type DownloadAction, ErrorBoundary, ErrorView, FallbackBlock, FilterBlock, InsightBlock, KpiBlock, Markdown, type MarkdownProps, type OnAction, type OpenLinkAction, RecommendationBlock, type RefreshAction, type RegisterBlockOptions, type StreamMessageOptions, TableBlock, TextBlock, type UseAiStreamOptions, type UseAiStreamResult, type UseChatOptions, type UseChatResult, createConversation, defaultBlockComponents, deleteConversation, getConversation, getMessages, listConversations, messageUrl, noopAction, registerBlock, registeredBlockTypes, renameConversation, resolveBlockComponent, streamMessage, unregisterBlock, useAiStream, useChat };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ComponentType, ReactNode, Component, ErrorInfo } from 'react';
|
|
3
|
+
import { Block, AiResponse, AiStreamState, ConversationSummary, MessageResponse, TextBlock as TextBlock$1, KpiBlock as KpiBlock$1, ChartBlock as ChartBlock$1, TableBlock as TableBlock$1, InsightBlock as InsightBlock$1, RecommendationBlock as RecommendationBlock$1, FilterBlock as FilterBlock$1, SseEvent } from '@responsekit/schema';
|
|
4
|
+
export * from '@responsekit/schema';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Actions are the SDK's single outbound channel. Blocks and custom components emit
|
|
8
|
+
* actions; the host app decides what they mean. The SDK NEVER runs business logic —
|
|
9
|
+
* it only forwards intent via `onAction`.
|
|
10
|
+
*/
|
|
11
|
+
interface DownloadAction {
|
|
12
|
+
type: "DOWNLOAD";
|
|
13
|
+
/** What to download — e.g. a table's rows, a chart's data, or a server-side artifact id. */
|
|
14
|
+
format?: "CSV" | "JSON" | string;
|
|
15
|
+
filename?: string;
|
|
16
|
+
data?: unknown;
|
|
17
|
+
/** The block that originated the action, when applicable. */
|
|
18
|
+
blockId?: string;
|
|
19
|
+
}
|
|
20
|
+
interface OpenLinkAction {
|
|
21
|
+
type: "OPEN_LINK";
|
|
22
|
+
href: string;
|
|
23
|
+
target?: "_blank" | "_self";
|
|
24
|
+
blockId?: string;
|
|
25
|
+
}
|
|
26
|
+
interface RefreshAction {
|
|
27
|
+
type: "REFRESH";
|
|
28
|
+
responseId?: string;
|
|
29
|
+
}
|
|
30
|
+
interface CustomAction {
|
|
31
|
+
type: "CUSTOM";
|
|
32
|
+
/** A host-defined action name, e.g. "DRILL_DOWN". */
|
|
33
|
+
name: string;
|
|
34
|
+
payload?: unknown;
|
|
35
|
+
blockId?: string;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Open union: the known actions plus an escape hatch for host- or plugin-defined ones.
|
|
39
|
+
* Consumers can narrow on `action.type`.
|
|
40
|
+
*/
|
|
41
|
+
type AiAction = DownloadAction | OpenLinkAction | RefreshAction | CustomAction | ({
|
|
42
|
+
type: string;
|
|
43
|
+
} & Record<string, unknown>);
|
|
44
|
+
type OnAction = (action: AiAction) => void;
|
|
45
|
+
/** A no-op default so components can always call `onAction` safely. */
|
|
46
|
+
declare const noopAction: OnAction;
|
|
47
|
+
|
|
48
|
+
/** Props every block component receives. */
|
|
49
|
+
interface BlockComponentProps<B extends Block = Block> {
|
|
50
|
+
block: B;
|
|
51
|
+
onAction: OnAction;
|
|
52
|
+
}
|
|
53
|
+
type BlockComponent<B extends Block = Block> = ComponentType<BlockComponentProps<B>>;
|
|
54
|
+
/**
|
|
55
|
+
* Override map passed to `<AiRenderer components={...} />`. Keys are block `type`
|
|
56
|
+
* strings; values replace the default component for that type. Custom (non-builtin)
|
|
57
|
+
* types are allowed too.
|
|
58
|
+
*/
|
|
59
|
+
type BlockComponents = Record<string, BlockComponent>;
|
|
60
|
+
|
|
61
|
+
interface AiRendererProps {
|
|
62
|
+
/** A complete response object (typically from `useAiStream().response`). */
|
|
63
|
+
response: AiResponse;
|
|
64
|
+
/** Per-render component overrides, keyed by block `type`. */
|
|
65
|
+
components?: BlockComponents;
|
|
66
|
+
/** Single outbound action channel. */
|
|
67
|
+
onAction?: OnAction;
|
|
68
|
+
className?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Renders a complete `AiResponse`. Switches on `response.type`:
|
|
72
|
+
* - TEXT → Markdown (when `format === "MARKDOWN"`) or plain text
|
|
73
|
+
* - ANALYTICS → optional title, then each block via the registry, in order
|
|
74
|
+
* - ERROR → error component
|
|
75
|
+
*
|
|
76
|
+
* Every block is wrapped in an error boundary and resolved through the registry, so
|
|
77
|
+
* unknown types or render failures degrade to a fallback rather than crashing.
|
|
78
|
+
*/
|
|
79
|
+
declare function AiRenderer({ response, components, onAction, className, }: AiRendererProps): react.JSX.Element;
|
|
80
|
+
declare function ErrorView({ message }: {
|
|
81
|
+
message: string;
|
|
82
|
+
}): react.JSX.Element;
|
|
83
|
+
|
|
84
|
+
interface UseAiStreamOptions {
|
|
85
|
+
baseUrl: string;
|
|
86
|
+
conversationId: string;
|
|
87
|
+
message: string;
|
|
88
|
+
headers?: Record<string, string>;
|
|
89
|
+
fetchImpl?: typeof fetch;
|
|
90
|
+
/**
|
|
91
|
+
* Auto-start the stream when `message` (and the endpoint) are set. Default true.
|
|
92
|
+
* Set false to control start/stop manually via the returned `start()`/`stop()`.
|
|
93
|
+
*/
|
|
94
|
+
enabled?: boolean;
|
|
95
|
+
}
|
|
96
|
+
interface UseAiStreamResult extends AiStreamState {
|
|
97
|
+
isStreaming: boolean;
|
|
98
|
+
/** (Re)start the stream. Aborts any in-flight stream first. */
|
|
99
|
+
start: () => void;
|
|
100
|
+
/** Abort the in-flight stream. */
|
|
101
|
+
stop: () => void;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Consume the SSE message stream and reduce its events into live `AiStreamState`.
|
|
105
|
+
* The response is assembled incrementally (blocks appended as they arrive).
|
|
106
|
+
*/
|
|
107
|
+
declare function useAiStream(options: UseAiStreamOptions): UseAiStreamResult;
|
|
108
|
+
|
|
109
|
+
interface AiStreamProps extends UseAiStreamOptions {
|
|
110
|
+
components?: BlockComponents;
|
|
111
|
+
onAction?: OnAction;
|
|
112
|
+
className?: string;
|
|
113
|
+
/** Custom loading UI. Receives the live progress state. */
|
|
114
|
+
renderLoading?: (state: AiStreamState) => ReactNode;
|
|
115
|
+
/** Custom error UI. */
|
|
116
|
+
renderError?: (error: string) => ReactNode;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* End-to-end: streams from `POST {baseUrl}/api/conversations/{id}/messages`, shows a
|
|
120
|
+
* progress-driven loading state, then renders the assembled response with `AiRenderer`.
|
|
121
|
+
*
|
|
122
|
+
* As soon as any response content exists it is rendered live (blocks appear in order);
|
|
123
|
+
* the loading indicator stays visible until the stream finishes.
|
|
124
|
+
*/
|
|
125
|
+
declare function AiStream({ components, onAction, className, renderLoading, renderError, ...streamOptions }: AiStreamProps): react.JSX.Element;
|
|
126
|
+
|
|
127
|
+
/** One user turn plus the assistant's (streaming or finished) response state. */
|
|
128
|
+
interface ChatTurn {
|
|
129
|
+
id: string;
|
|
130
|
+
userMessage: string;
|
|
131
|
+
/** Live stream state for this turn; `state.response` is the assembled AiResponse. */
|
|
132
|
+
state: AiStreamState;
|
|
133
|
+
}
|
|
134
|
+
interface UseChatOptions {
|
|
135
|
+
baseUrl: string;
|
|
136
|
+
/**
|
|
137
|
+
* Use an existing conversation. If omitted, a conversation is created lazily on the
|
|
138
|
+
* first `send()` (via POST /api/conversations).
|
|
139
|
+
*/
|
|
140
|
+
conversationId?: string;
|
|
141
|
+
/** Title for the auto-created conversation. Defaults to the first message (truncated). */
|
|
142
|
+
titleFor?: (firstMessage: string) => string;
|
|
143
|
+
headers?: Record<string, string>;
|
|
144
|
+
fetchImpl?: typeof fetch;
|
|
145
|
+
}
|
|
146
|
+
interface UseChatResult {
|
|
147
|
+
conversationId?: string;
|
|
148
|
+
turns: ChatTurn[];
|
|
149
|
+
isStreaming: boolean;
|
|
150
|
+
error?: string;
|
|
151
|
+
/** Send a message. Creates the conversation first if needed. */
|
|
152
|
+
send: (message: string) => Promise<void>;
|
|
153
|
+
/** Abort the in-flight stream (if any). */
|
|
154
|
+
stop: () => void;
|
|
155
|
+
/** Clear all turns (keeps the conversation id). */
|
|
156
|
+
reset: () => void;
|
|
157
|
+
/** Start a brand-new conversation: clears turns and drops the id so the next
|
|
158
|
+
* `send()` creates a fresh conversation. */
|
|
159
|
+
newConversation: () => void;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Drive a multi-message conversation: one conversation id, an ordered list of turns,
|
|
163
|
+
* each assistant response assembled incrementally from the SSE stream. Built directly
|
|
164
|
+
* on `streamMessage` + `streamReducer` so it stays a thin, predictable layer.
|
|
165
|
+
*/
|
|
166
|
+
declare function useChat(options: UseChatOptions): UseChatResult;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Framework-agnostic REST client for the conversation lifecycle.
|
|
170
|
+
*
|
|
171
|
+
* The SDK's core job is message → render, but hosts still need to create/list/rename
|
|
172
|
+
* conversations. These are thin, dependency-free `fetch` wrappers over the backend's
|
|
173
|
+
* plain REST endpoints, kept optional so the render path stays lean. (Lives next to
|
|
174
|
+
* `streamMessage`; both are UI-agnostic and could move to a `core` package later.)
|
|
175
|
+
*/
|
|
176
|
+
interface ConversationClientOptions {
|
|
177
|
+
baseUrl: string;
|
|
178
|
+
/** Extra headers (e.g. Authorization) merged onto every request. */
|
|
179
|
+
headers?: Record<string, string>;
|
|
180
|
+
signal?: AbortSignal;
|
|
181
|
+
/** Injectable fetch (tests / non-browser runtimes). Defaults to global `fetch`. */
|
|
182
|
+
fetchImpl?: typeof fetch;
|
|
183
|
+
}
|
|
184
|
+
/** POST /api/conversations — create a conversation. */
|
|
185
|
+
declare function createConversation(opts: ConversationClientOptions & {
|
|
186
|
+
title?: string;
|
|
187
|
+
}): Promise<ConversationSummary>;
|
|
188
|
+
/** GET /api/conversations — list conversations. */
|
|
189
|
+
declare function listConversations(opts: ConversationClientOptions): Promise<ConversationSummary[]>;
|
|
190
|
+
/** GET /api/conversations/{id} — fetch one conversation. */
|
|
191
|
+
declare function getConversation(opts: ConversationClientOptions & {
|
|
192
|
+
conversationId: string;
|
|
193
|
+
}): Promise<ConversationSummary>;
|
|
194
|
+
/** PATCH /api/conversations/{id} — rename a conversation. */
|
|
195
|
+
declare function renameConversation(opts: ConversationClientOptions & {
|
|
196
|
+
conversationId: string;
|
|
197
|
+
title: string;
|
|
198
|
+
}): Promise<ConversationSummary>;
|
|
199
|
+
/** DELETE /api/conversations/{id}. */
|
|
200
|
+
declare function deleteConversation(opts: ConversationClientOptions & {
|
|
201
|
+
conversationId: string;
|
|
202
|
+
}): Promise<void>;
|
|
203
|
+
/** GET /api/conversations/{id}/messages — load prior messages (history). */
|
|
204
|
+
declare function getMessages(opts: ConversationClientOptions & {
|
|
205
|
+
conversationId: string;
|
|
206
|
+
}): Promise<MessageResponse[]>;
|
|
207
|
+
|
|
208
|
+
interface RegisterBlockOptions {
|
|
209
|
+
type: string;
|
|
210
|
+
component: BlockComponent;
|
|
211
|
+
/** When false, does not replace an existing global registration. Default true. */
|
|
212
|
+
override?: boolean;
|
|
213
|
+
}
|
|
214
|
+
/** Register a custom/unknown block type globally (extension point). */
|
|
215
|
+
declare function registerBlock(options: RegisterBlockOptions): void;
|
|
216
|
+
/** Remove a global registration (mainly for tests/cleanup). */
|
|
217
|
+
declare function unregisterBlock(type: string): void;
|
|
218
|
+
/** Snapshot of globally registered types. */
|
|
219
|
+
declare function registeredBlockTypes(): string[];
|
|
220
|
+
/**
|
|
221
|
+
* Resolve the component for a block type. Always returns a component — never null —
|
|
222
|
+
* falling back to `FallbackBlock` so rendering can never crash on an unknown type.
|
|
223
|
+
*/
|
|
224
|
+
declare function resolveBlockComponent(type: string, overrides?: BlockComponents): BlockComponent;
|
|
225
|
+
|
|
226
|
+
/** A block-level TEXT node. Rendered as (safe) Markdown. */
|
|
227
|
+
declare function TextBlock({ block }: BlockComponentProps<TextBlock$1>): react.JSX.Element;
|
|
228
|
+
|
|
229
|
+
declare function KpiBlock({ block }: BlockComponentProps<KpiBlock$1>): react.JSX.Element;
|
|
230
|
+
|
|
231
|
+
declare function ChartBlock({ block }: BlockComponentProps<ChartBlock$1>): react.JSX.Element;
|
|
232
|
+
|
|
233
|
+
declare function TableBlock({ block, onAction }: BlockComponentProps<TableBlock$1>): react.JSX.Element;
|
|
234
|
+
|
|
235
|
+
declare function InsightBlock({ block }: BlockComponentProps<InsightBlock$1>): react.JSX.Element;
|
|
236
|
+
|
|
237
|
+
declare function RecommendationBlock({ block, }: BlockComponentProps<RecommendationBlock$1>): react.JSX.Element;
|
|
238
|
+
|
|
239
|
+
declare function FilterBlock({ block }: BlockComponentProps<FilterBlock$1>): react.JSX.Element;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The graceful catch-all. Rendered for unknown block types, or known types whose
|
|
243
|
+
* required fields were missing/invalid (the parser coerces those to UnknownBlock).
|
|
244
|
+
* Never throws; optionally shows the raw payload in dev to aid debugging.
|
|
245
|
+
*/
|
|
246
|
+
declare function FallbackBlock({ block }: BlockComponentProps<Block>): react.JSX.Element;
|
|
247
|
+
|
|
248
|
+
/** The built-in block components, keyed by block `type`. */
|
|
249
|
+
declare const defaultBlockComponents: BlockComponents;
|
|
250
|
+
|
|
251
|
+
interface MarkdownProps {
|
|
252
|
+
children: string;
|
|
253
|
+
className?: string;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Renders AI-authored Markdown safely.
|
|
257
|
+
*
|
|
258
|
+
* Security posture (see the prompt's non-negotiables):
|
|
259
|
+
* - GitHub-flavored Markdown via `remark-gfm`.
|
|
260
|
+
* - NO `rehype-raw`: raw HTML in the source is treated as text, never parsed/injected.
|
|
261
|
+
* - `react-markdown` builds a React tree — no `dangerouslySetInnerHTML` anywhere.
|
|
262
|
+
* - URLs are passed through react-markdown's default transform, which strips
|
|
263
|
+
* dangerous protocols (javascript:, data:, etc.). Links open in a new tab with
|
|
264
|
+
* `rel="noopener noreferrer"`.
|
|
265
|
+
*/
|
|
266
|
+
declare function Markdown({ children, className }: MarkdownProps): react.JSX.Element;
|
|
267
|
+
|
|
268
|
+
interface Props {
|
|
269
|
+
children: ReactNode;
|
|
270
|
+
fallback: (error: Error) => ReactNode;
|
|
271
|
+
onError?: (error: Error, info: ErrorInfo) => void;
|
|
272
|
+
}
|
|
273
|
+
interface State {
|
|
274
|
+
error: Error | null;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Catches render-time errors from a single block/subtree so one bad custom component
|
|
278
|
+
* (or an unexpected data shape) can degrade to a fallback instead of taking down the
|
|
279
|
+
* whole host app. This backs the "never crash" guarantee at the render layer, on top
|
|
280
|
+
* of the schema-level validation.
|
|
281
|
+
*/
|
|
282
|
+
declare class ErrorBoundary extends Component<Props, State> {
|
|
283
|
+
state: State;
|
|
284
|
+
static getDerivedStateFromError(error: Error): State;
|
|
285
|
+
componentDidCatch(error: Error, info: ErrorInfo): void;
|
|
286
|
+
render(): ReactNode;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* SSE transport. The message endpoint is POST and streams `text/event-stream`, so the
|
|
291
|
+
* native `EventSource` (GET-only) cannot be used — we drive `fetch` + `ReadableStream`
|
|
292
|
+
* and parse the SSE framing by hand.
|
|
293
|
+
*/
|
|
294
|
+
interface StreamMessageOptions {
|
|
295
|
+
baseUrl: string;
|
|
296
|
+
conversationId: string;
|
|
297
|
+
message: string;
|
|
298
|
+
/** Extra headers (e.g. Authorization) merged onto the request. */
|
|
299
|
+
headers?: Record<string, string>;
|
|
300
|
+
signal?: AbortSignal;
|
|
301
|
+
/** Injectable fetch (tests / non-browser runtimes). Defaults to global `fetch`. */
|
|
302
|
+
fetchImpl?: typeof fetch;
|
|
303
|
+
}
|
|
304
|
+
/** Build the POST message URL for a conversation. */
|
|
305
|
+
declare function messageUrl(baseUrl: string, conversationId: string): string;
|
|
306
|
+
/**
|
|
307
|
+
* Open the stream and yield typed `SseEvent`s as they arrive. Never throws for
|
|
308
|
+
* transport/parse problems — it yields a terminal `error` event instead, so the
|
|
309
|
+
* reducer/host always sees a clean signal.
|
|
310
|
+
*/
|
|
311
|
+
declare function streamMessage(options: StreamMessageOptions): AsyncGenerator<SseEvent>;
|
|
312
|
+
|
|
313
|
+
export { type AiAction, AiRenderer, type AiRendererProps, AiStream, type AiStreamProps, type BlockComponent, type BlockComponentProps, type BlockComponents, ChartBlock, type ChatTurn, type ConversationClientOptions, type CustomAction, type DownloadAction, ErrorBoundary, ErrorView, FallbackBlock, FilterBlock, InsightBlock, KpiBlock, Markdown, type MarkdownProps, type OnAction, type OpenLinkAction, RecommendationBlock, type RefreshAction, type RegisterBlockOptions, type StreamMessageOptions, TableBlock, TextBlock, type UseAiStreamOptions, type UseAiStreamResult, type UseChatOptions, type UseChatResult, createConversation, defaultBlockComponents, deleteConversation, getConversation, getMessages, listConversations, messageUrl, noopAction, registerBlock, registeredBlockTypes, renameConversation, resolveBlockComponent, streamMessage, unregisterBlock, useAiStream, useChat };
|