@coral-ai/chat 0.3.0 → 0.4.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 +7 -10
- package/dist/index.d.ts +489 -87
- package/dist/index.js +1711 -466
- package/dist/index.js.map +1 -1
- package/package.json +8 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,38 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import React__default, { ReactNode } from 'react';
|
|
2
3
|
import { ChatFontSize, ChatFontFamily } from '@coral-ai/markdown';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
5
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
onSendMessage
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;
|
|
25
|
-
/** Called when an error occurs during send. */
|
|
26
|
-
onError?: (err: unknown) => void;
|
|
27
|
-
/** Automatically sends this message once on mount. */
|
|
28
|
-
autoSendMessage?: string;
|
|
29
|
-
/** Override the thinking indicator text during generation. */
|
|
30
|
-
thinkingStatus?: string;
|
|
31
|
-
/** Called when the user clicks Stop. Use to abort your fetch/API call. */
|
|
32
|
-
onStop?: () => void;
|
|
33
|
-
children?: ReactNode;
|
|
6
|
+
type ErrorCategory = "auth_billing" | "rate_limit" | "overloaded" | "bad_input" | "not_found" | "server_error" | "unknown";
|
|
7
|
+
/**
|
|
8
|
+
* A categorized, user-friendly error. This shape is JSON-serializable so it
|
|
9
|
+
* can be stored on a `ChatMessage` and survive persistence / rehydration.
|
|
10
|
+
*/
|
|
11
|
+
interface NormalizedChatError {
|
|
12
|
+
category: ErrorCategory;
|
|
13
|
+
message: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Normalizes raw errors from Anthropic, OpenAI, and Google Gemini into a
|
|
17
|
+
* common category + user-friendly message. Safe to call with any unknown value.
|
|
18
|
+
* Idempotent — passing an already-normalized error returns it unchanged.
|
|
19
|
+
*/
|
|
20
|
+
declare function normalizeChatError$1(err: unknown): NormalizedChatError;
|
|
21
|
+
interface ChatErrorProps {
|
|
22
|
+
/** Raw error thrown by your onSendMessage handler — any provider shape works. */
|
|
23
|
+
error: unknown;
|
|
24
|
+
/** Optional retry callback shown as a button. */
|
|
25
|
+
onRetry?: () => void;
|
|
34
26
|
}
|
|
35
|
-
declare const
|
|
27
|
+
declare const ChatError: React__default.FC<ChatErrorProps>;
|
|
36
28
|
|
|
37
29
|
type ChatMessage = {
|
|
38
30
|
/** Stable identifier — generated automatically by Chat.Canvas. Used as React key. */
|
|
@@ -43,19 +35,93 @@ type ChatMessage = {
|
|
|
43
35
|
type?: string;
|
|
44
36
|
/** Arbitrary data passed to the custom renderer for this message. */
|
|
45
37
|
metadata?: Record<string, unknown>;
|
|
38
|
+
/**
|
|
39
|
+
* If present, this assistant message carries a structured approval request.
|
|
40
|
+
* Rendered above Chat.Input as a pinned selector while `answer` is undefined;
|
|
41
|
+
* once answered, it stays in history with `answer` populated for replay.
|
|
42
|
+
*/
|
|
43
|
+
approval?: ChatApprovalRequest;
|
|
44
|
+
/**
|
|
45
|
+
* If present, this assistant message carries a multi-step task plan.
|
|
46
|
+
* Rendered inline as a collapsible checklist above the message text and
|
|
47
|
+
* persists in history for replay. Updated in place as the agent streams.
|
|
48
|
+
*/
|
|
49
|
+
todos?: ChatTodo[];
|
|
50
|
+
/**
|
|
51
|
+
* If present, the turn that produced this assistant message failed. The
|
|
52
|
+
* message renders as an error card (with a Retry button) instead of normal
|
|
53
|
+
* content. Persisted with the conversation so the error survives reloads.
|
|
54
|
+
*/
|
|
55
|
+
error?: NormalizedChatError;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* One option in a human-in-the-loop approval / multiple-choice prompt.
|
|
59
|
+
* Boolean approval is just two options; N-choice is the same shape with N options.
|
|
60
|
+
*/
|
|
61
|
+
type ApprovalOption = {
|
|
62
|
+
id: string;
|
|
63
|
+
label: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
appearance?: "primary" | "subtle" | "outline" | "secondary";
|
|
66
|
+
/**
|
|
67
|
+
* When true, selecting this option does NOT immediately resolve the approval.
|
|
68
|
+
* The chat input is unlocked so the user can type a free-text reply, which is
|
|
69
|
+
* then sent as the resolution payload (carrying this option's id alongside the text).
|
|
70
|
+
* Convention: a final "Other / something else" choice.
|
|
71
|
+
*/
|
|
72
|
+
freeform?: boolean;
|
|
73
|
+
};
|
|
74
|
+
/** Structured approval request attached to an assistant message. */
|
|
75
|
+
type ChatApprovalRequest = {
|
|
76
|
+
/** Stable id used to match the eventual response. */
|
|
77
|
+
id: string;
|
|
78
|
+
question: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
options: ApprovalOption[];
|
|
81
|
+
/**
|
|
82
|
+
* Once the user responds, this is populated and the buttons render in their
|
|
83
|
+
* "answered" terminal state. Distinct from `freeform` so freeform replies
|
|
84
|
+
* still record which option was the escape hatch.
|
|
85
|
+
*/
|
|
86
|
+
answer?: {
|
|
87
|
+
optionId: string;
|
|
88
|
+
text?: string;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* One step in a multi-step task plan. The agent emits the whole list on each
|
|
93
|
+
* update; the convention is exactly one item `in_progress` at a time.
|
|
94
|
+
*/
|
|
95
|
+
type ChatTodo = {
|
|
96
|
+
/** Stable id for React key + diffing. Optional; index used as fallback. */
|
|
97
|
+
id?: string;
|
|
98
|
+
/** Imperative title shown when pending/completed, e.g. "Optimize images". */
|
|
99
|
+
content: string;
|
|
100
|
+
/** Present-tense title shown while in_progress, e.g. "Optimizing images". */
|
|
101
|
+
activeForm?: string;
|
|
102
|
+
status: "pending" | "in_progress" | "completed";
|
|
46
103
|
};
|
|
47
104
|
/** A single chunk yielded by a streaming onSendMessage. */
|
|
48
105
|
type ChatChunk = string | {
|
|
49
106
|
type: "reasoning";
|
|
50
107
|
content: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
108
|
+
}
|
|
109
|
+
/** Sets the thinking-indicator word pool while the handler works. */
|
|
110
|
+
| {
|
|
111
|
+
type: "status";
|
|
53
112
|
name: string;
|
|
113
|
+
} | {
|
|
114
|
+
type: "approval";
|
|
115
|
+
approval: ChatApprovalRequest;
|
|
116
|
+
} | {
|
|
117
|
+
type: "todos";
|
|
118
|
+
todos: ChatTodo[];
|
|
54
119
|
};
|
|
55
120
|
type ChatResponse = string | AsyncIterable<ChatChunk> | {
|
|
56
121
|
content: string;
|
|
57
122
|
type?: string;
|
|
58
123
|
metadata?: Record<string, unknown>;
|
|
124
|
+
todos?: ChatTodo[];
|
|
59
125
|
};
|
|
60
126
|
/** The typed handler signature engineers implement. */
|
|
61
127
|
type ChatAttachment = {
|
|
@@ -71,11 +137,20 @@ type ChatMessageRendererProps = {
|
|
|
71
137
|
/** Sends a message back into the chat as the user. */
|
|
72
138
|
onReply: (content: string) => void;
|
|
73
139
|
};
|
|
74
|
-
type ChatComponents = Record<string,
|
|
140
|
+
type ChatComponents = Record<string, React__default.FC<ChatMessageRendererProps>>;
|
|
75
141
|
interface ChatProps {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Backend URL. Coral POSTs `{ text, history, attachments }` here on send and
|
|
144
|
+
* adapts the response to the existing chat pipeline. Used only when no
|
|
145
|
+
* `onSendMessage` is provided. Falls back to `useCoralConfig().chat.api`
|
|
146
|
+
* when omitted.
|
|
147
|
+
*/
|
|
148
|
+
api?: string;
|
|
149
|
+
/**
|
|
150
|
+
* Which entries to render in the chat input's `+` menu. Falls back to
|
|
151
|
+
* `useCoralConfig().chat.attachments` when omitted.
|
|
152
|
+
*/
|
|
153
|
+
allowedAttachments?: Array<"files" | "photos">;
|
|
79
154
|
conversationId?: string;
|
|
80
155
|
initialMessages?: ChatMessage[];
|
|
81
156
|
systemPrompt?: string;
|
|
@@ -85,7 +160,6 @@ interface ChatProps {
|
|
|
85
160
|
onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;
|
|
86
161
|
onError?: (err: unknown) => void;
|
|
87
162
|
autoSendMessage?: string;
|
|
88
|
-
onFeedback?: (messageIndex: number, rating: "up" | "down") => void;
|
|
89
163
|
onCopy?: (content: string) => void;
|
|
90
164
|
onNavigate?: (path: string) => void;
|
|
91
165
|
components?: ChatComponents;
|
|
@@ -96,20 +170,18 @@ interface ChatProps {
|
|
|
96
170
|
/** Disables the entire input. */
|
|
97
171
|
disabled?: boolean;
|
|
98
172
|
/** Slot rendered at the left of the input toolbar. */
|
|
99
|
-
actionsStart?:
|
|
173
|
+
actionsStart?: React__default.ReactNode;
|
|
100
174
|
/** Slot rendered at the right of the input toolbar, just before Send/Stop. */
|
|
101
|
-
actionsEnd?:
|
|
102
|
-
/** Shown 24px above the input while messages is empty. */
|
|
103
|
-
emptyState?: React.ReactNode;
|
|
175
|
+
actionsEnd?: React__default.ReactNode;
|
|
104
176
|
/**
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
* any
|
|
177
|
+
* Shown above the input while messages is empty.
|
|
178
|
+
* - Pass a `string` to render it as a `Title3` heading that hugs its content.
|
|
179
|
+
* - Pass any other `ReactNode` to flex-fill the available height (centered).
|
|
108
180
|
*/
|
|
109
|
-
|
|
181
|
+
welcomeMessage?: string | React__default.ReactNode;
|
|
110
182
|
/**
|
|
111
183
|
* Pass `null` to disable the chat's built-in surface motion (input slide to
|
|
112
|
-
* bottom
|
|
184
|
+
* bottom on first message). Omit / leave undefined for default motion.
|
|
113
185
|
*/
|
|
114
186
|
surfaceMotion?: null;
|
|
115
187
|
/** Font size for assistant message markdown. */
|
|
@@ -117,7 +189,46 @@ interface ChatProps {
|
|
|
117
189
|
/** Font family for assistant message markdown. */
|
|
118
190
|
fontFamily?: ChatFontFamily;
|
|
119
191
|
}
|
|
120
|
-
declare const Chat$1:
|
|
192
|
+
declare const Chat$1: React__default.FC<ChatProps>;
|
|
193
|
+
|
|
194
|
+
interface ChatCanvasProps {
|
|
195
|
+
/**
|
|
196
|
+
* Backend URL Coral POSTs to on send. Used as the built-in handler when
|
|
197
|
+
* `onSendMessage` is not set.
|
|
198
|
+
*
|
|
199
|
+
* Coral serializes attachments to base64 and sends
|
|
200
|
+
* `{ text, history, attachments: [{ name, mediaType, data }] }` as JSON. The
|
|
201
|
+
* response can be `{ type?, reply }` (non-streaming) or a Server-Sent-Events
|
|
202
|
+
* stream of `ChatChunk` JSON lines. The optional `type` field is matched
|
|
203
|
+
* against Coral's built-in task vocabulary to pick the thinking-indicator
|
|
204
|
+
* word pool.
|
|
205
|
+
*/
|
|
206
|
+
api?: string;
|
|
207
|
+
/** Which entries to render in the chat input's `+` menu (`Chat.AttachButton`). */
|
|
208
|
+
allowedAttachments?: Array<"files" | "photos">;
|
|
209
|
+
/** Stable conversation identifier, passed back in onMessageComplete. */
|
|
210
|
+
conversationId?: string;
|
|
211
|
+
/** Pre-load conversation history. */
|
|
212
|
+
initialMessages?: ChatMessage[];
|
|
213
|
+
/** System prompt prepended to every request (not shown in UI). */
|
|
214
|
+
systemPrompt?: string;
|
|
215
|
+
/** Called when the user sends a message. Return a string, async iterable, or ChatResponse. */
|
|
216
|
+
onSendMessage?: (input: string, history: ChatMessage[], attachments: File[]) => ReturnType<AgentHandler>;
|
|
217
|
+
/** Called after every completed assistant response. Use to persist messages. */
|
|
218
|
+
onMessageComplete?: (messages: ChatMessage[], conversationId?: string) => void;
|
|
219
|
+
/** Called on every message-state update (user append, streaming chunk, final). Use for live persistence. */
|
|
220
|
+
onMessagesChange?: (messages: ChatMessage[], conversationId?: string) => void;
|
|
221
|
+
/** Called when an error occurs during send. */
|
|
222
|
+
onError?: (err: unknown) => void;
|
|
223
|
+
/** Automatically sends this message once on mount. */
|
|
224
|
+
autoSendMessage?: string;
|
|
225
|
+
/** Override the thinking indicator text during generation. */
|
|
226
|
+
thinkingStatus?: string;
|
|
227
|
+
/** Called when the user clicks Stop. Use to abort your fetch/API call. */
|
|
228
|
+
onStop?: () => void;
|
|
229
|
+
children?: ReactNode;
|
|
230
|
+
}
|
|
231
|
+
declare const ChatCanvas: React__default.FC<ChatCanvasProps>;
|
|
121
232
|
|
|
122
233
|
interface ChatMessagesProps {
|
|
123
234
|
/**
|
|
@@ -125,8 +236,6 @@ interface ChatMessagesProps {
|
|
|
125
236
|
* Falls back to default markdown rendering if no match.
|
|
126
237
|
*/
|
|
127
238
|
components?: ChatComponents;
|
|
128
|
-
/** Called when the user clicks thumbs-up on an assistant message. */
|
|
129
|
-
onFeedback?: (messageIndex: number, rating: "up" | "down") => void;
|
|
130
239
|
/** Called when the user copies an assistant message. */
|
|
131
240
|
onCopy?: (content: string) => void;
|
|
132
241
|
/** Called when the user clicks an internal link (href starts with "/"). */
|
|
@@ -136,7 +245,31 @@ interface ChatMessagesProps {
|
|
|
136
245
|
/** Font family for assistant message markdown. */
|
|
137
246
|
fontFamily?: ChatFontFamily;
|
|
138
247
|
}
|
|
139
|
-
declare const ChatMessages:
|
|
248
|
+
declare const ChatMessages: React__default.FC<ChatMessagesProps>;
|
|
249
|
+
|
|
250
|
+
type ChatAttachType = "files" | "photos";
|
|
251
|
+
interface ChatAttachButtonProps {
|
|
252
|
+
/**
|
|
253
|
+
* Which entries to render in the `+` menu. Order in the array is the order
|
|
254
|
+
* shown in the menu. Defaults to `['files', 'photos']`.
|
|
255
|
+
*/
|
|
256
|
+
types?: ChatAttachType[];
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* The "+" button rendered by default to the left of the chat input toolbar.
|
|
260
|
+
*
|
|
261
|
+
* Opens a Fluent menu with "Add files" / "Add photos" entries (subset
|
|
262
|
+
* controlled by `types`). Selecting one opens the native OS file picker via a
|
|
263
|
+
* hidden `<input type="file">` and pushes the resulting `File[]` through
|
|
264
|
+
* `addAttachments` on `useChatContext`. From there the existing chat pipeline
|
|
265
|
+
* stages the files, renders preview tiles above the textarea, and hands the
|
|
266
|
+
* raw `File[]` to the agent handler on send.
|
|
267
|
+
*
|
|
268
|
+
* Engineers don't typically render this directly — `<Chat allowedAttachments>`
|
|
269
|
+
* does it for them. It's exported so the same component can be dropped into
|
|
270
|
+
* `actionsStart` for fully custom layouts.
|
|
271
|
+
*/
|
|
272
|
+
declare const ChatAttachButton: React__default.FC<ChatAttachButtonProps>;
|
|
140
273
|
|
|
141
274
|
interface ChatInputProps {
|
|
142
275
|
/** Current input value. Optional inside Chat.Canvas — auto-wired from context. */
|
|
@@ -148,51 +281,91 @@ interface ChatInputProps {
|
|
|
148
281
|
placeholder?: string;
|
|
149
282
|
/** Disabled state. */
|
|
150
283
|
disabled?: boolean;
|
|
151
|
-
style?:
|
|
284
|
+
style?: React__default.CSSProperties;
|
|
152
285
|
/** Slot rendered at the left of the bottom toolbar. */
|
|
153
|
-
actionsStart?:
|
|
286
|
+
actionsStart?: React__default.ReactNode;
|
|
154
287
|
/** Slot rendered at the right of the bottom toolbar, just before Send/Stop. */
|
|
155
|
-
actionsEnd?:
|
|
288
|
+
actionsEnd?: React__default.ReactNode;
|
|
156
289
|
/** Override attachments when used outside a Chat.Canvas. */
|
|
157
290
|
attachments?: ChatAttachment[];
|
|
158
291
|
/** Override remove handler when used outside a Chat.Canvas. */
|
|
159
292
|
removeAttachment?: (id: string) => void;
|
|
293
|
+
/**
|
|
294
|
+
* Renders the `+` (Chat.AttachButton) menu before `actionsStart` content.
|
|
295
|
+
* When omitted, falls back to the value in `useChatContext().allowedAttachments`
|
|
296
|
+
* (set by Chat / Chat.Canvas via the `allowedAttachments` prop). When both are
|
|
297
|
+
* undefined, no `+` button renders — current behavior preserved.
|
|
298
|
+
*/
|
|
299
|
+
allowedAttachments?: ChatAttachType[];
|
|
160
300
|
}
|
|
161
|
-
declare const ChatInput:
|
|
301
|
+
declare const ChatInput: React__default.ForwardRefExoticComponent<ChatInputProps & React__default.RefAttributes<HTMLTextAreaElement>>;
|
|
162
302
|
|
|
163
|
-
|
|
164
|
-
interface NormalizedError {
|
|
165
|
-
category: ErrorCategory;
|
|
303
|
+
interface ChatCalloutProps {
|
|
166
304
|
message: string;
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Normalizes raw errors from Anthropic, OpenAI, and Google Gemini into a
|
|
170
|
-
* common category + user-friendly message. Safe to call with any unknown value.
|
|
171
|
-
*/
|
|
172
|
-
declare function normalizeChatError$1(err: unknown): NormalizedError;
|
|
173
|
-
interface ChatErrorProps {
|
|
174
|
-
/** Raw error thrown by your onSendMessage handler — any provider shape works. */
|
|
175
|
-
error: unknown;
|
|
176
|
-
/** Optional retry callback shown as a button. */
|
|
177
305
|
onRetry?: () => void;
|
|
306
|
+
className?: string;
|
|
178
307
|
}
|
|
179
|
-
declare const
|
|
308
|
+
declare const ChatCallout: React__default.FC<ChatCalloutProps>;
|
|
180
309
|
|
|
181
|
-
interface
|
|
182
|
-
|
|
183
|
-
|
|
310
|
+
interface ChatApprovalProps {
|
|
311
|
+
/**
|
|
312
|
+
* Override the approval request to render. Defaults to `pendingApproval`
|
|
313
|
+
* from context. Useful for storybook / standalone previews.
|
|
314
|
+
*/
|
|
315
|
+
approval?: ChatApprovalRequest | null;
|
|
316
|
+
/**
|
|
317
|
+
* Override the resolver. Defaults to `resolveApproval` from context.
|
|
318
|
+
*/
|
|
319
|
+
onSelect?: (optionId: string) => void;
|
|
320
|
+
/** Disable all buttons. Defaults to false. */
|
|
321
|
+
disabled?: boolean;
|
|
322
|
+
className?: string;
|
|
323
|
+
style?: React__default.CSSProperties;
|
|
324
|
+
}
|
|
325
|
+
declare const ChatApproval: React__default.FC<ChatApprovalProps>;
|
|
326
|
+
|
|
327
|
+
interface ChatTodoListProps {
|
|
328
|
+
/** The current task plan. The whole list is replaced on each agent update. */
|
|
329
|
+
todos: ChatTodo[];
|
|
184
330
|
className?: string;
|
|
331
|
+
style?: React__default.CSSProperties;
|
|
185
332
|
}
|
|
186
|
-
declare const
|
|
333
|
+
declare const ChatTodoList: React__default.FC<ChatTodoListProps>;
|
|
334
|
+
|
|
335
|
+
interface ThinkingIndicatorProps {
|
|
336
|
+
isRetrying?: boolean;
|
|
337
|
+
/** Override the cycling animation with a static status string. The animated icon is retained. */
|
|
338
|
+
status?: string;
|
|
339
|
+
/**
|
|
340
|
+
* Override the pool of cycling words. Falls back to the default `thinkingMessages`
|
|
341
|
+
* pool when omitted. Ignored while `isRetrying` is true (retry uses its own pool).
|
|
342
|
+
*/
|
|
343
|
+
messages?: string[];
|
|
344
|
+
}
|
|
345
|
+
declare const ThinkingIndicator: React__default.FC<ThinkingIndicatorProps>;
|
|
187
346
|
|
|
188
347
|
type CreateHandlerOptions = {
|
|
189
|
-
/** Your backend endpoint. Receives POST { input, history,
|
|
348
|
+
/** Your backend endpoint. Receives POST { input, history, attachments }. */
|
|
190
349
|
endpoint: string;
|
|
191
350
|
/** Additional headers (e.g. Authorization). */
|
|
192
351
|
headers?: HeadersInit;
|
|
193
352
|
};
|
|
194
353
|
/**
|
|
195
354
|
* Wraps a fetch endpoint into an AgentHandler.
|
|
355
|
+
*
|
|
356
|
+
* On send it POSTs JSON to `endpoint`:
|
|
357
|
+
*
|
|
358
|
+
* ```json
|
|
359
|
+
* {
|
|
360
|
+
* "input": "the user's latest message",
|
|
361
|
+
* "history": [{ "role": "user", "content": "..." }],
|
|
362
|
+
* "attachments": [{ "name": "cat.jpg", "mediaType": "image/jpeg", "data": "<base64>" }]
|
|
363
|
+
* }
|
|
364
|
+
* ```
|
|
365
|
+
*
|
|
366
|
+
* Attached files are base64-encoded with `fileToBase64` (same encoding as
|
|
367
|
+
* Coral's built-in `api` handler); `attachments` is `[]` when none are staged.
|
|
368
|
+
*
|
|
196
369
|
* The endpoint should stream newline-delimited responses where each line is either:
|
|
197
370
|
* - A plain text chunk (yielded as a string)
|
|
198
371
|
* - A JSON-encoded ChatChunk object (e.g. `{"type":"reasoning","content":"..."}`)
|
|
@@ -200,53 +373,282 @@ type CreateHandlerOptions = {
|
|
|
200
373
|
* - `[DONE]` to signal end-of-stream
|
|
201
374
|
*
|
|
202
375
|
* @example
|
|
203
|
-
*
|
|
204
|
-
* <CoralProvider agents={{ default: { handler: createHandler({ endpoint: '/api/chat' }) } }}>
|
|
376
|
+
* <Chat onSendMessage={createHandler({ endpoint: '/api/chat' })} />
|
|
205
377
|
*/
|
|
206
378
|
declare function createHandler$1({ endpoint, headers }: CreateHandlerOptions): AgentHandler;
|
|
207
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Model-agnostic agent tool-use runner.
|
|
382
|
+
*
|
|
383
|
+
* `createAgentHandler` turns a provider-neutral `callModel` adapter into a
|
|
384
|
+
* Coral `AgentHandler`. Coral owns the tool-use loop, the built-in
|
|
385
|
+
* `update_todos` / `request_approval` tools, and the approval pause/resume
|
|
386
|
+
* bridge. The engineer owns exactly one function — `callModel` — which is the
|
|
387
|
+
* only provider-specific code (Claude, Azure OpenAI, …).
|
|
388
|
+
*/
|
|
389
|
+
/** A tool definition. `parameters` is standard JSON Schema for the tool input. */
|
|
390
|
+
type ToolSpec = {
|
|
391
|
+
name: string;
|
|
392
|
+
description: string;
|
|
393
|
+
parameters: Record<string, unknown>;
|
|
394
|
+
};
|
|
395
|
+
/** A tool invocation emitted by the model. */
|
|
396
|
+
type ToolCall = {
|
|
397
|
+
id: string;
|
|
398
|
+
name: string;
|
|
399
|
+
input: unknown;
|
|
400
|
+
};
|
|
401
|
+
/**
|
|
402
|
+
* One message in the neutral agent conversation. `raw` on assistant messages
|
|
403
|
+
* is an opaque passthrough for provider-native content blocks (e.g. Claude
|
|
404
|
+
* `thinking` + `tool_use` blocks that must replay verbatim across the loop) —
|
|
405
|
+
* the runner never inspects it; the adapter prefers it when rebuilding.
|
|
406
|
+
*/
|
|
407
|
+
type AgentMessage = {
|
|
408
|
+
role: "user";
|
|
409
|
+
content: string;
|
|
410
|
+
} | {
|
|
411
|
+
role: "assistant";
|
|
412
|
+
content: string;
|
|
413
|
+
toolCalls?: ToolCall[];
|
|
414
|
+
raw?: unknown;
|
|
415
|
+
} | {
|
|
416
|
+
role: "tool";
|
|
417
|
+
toolCallId: string;
|
|
418
|
+
content: string;
|
|
419
|
+
};
|
|
420
|
+
/** What the runner hands the `callModel` adapter for each model call. */
|
|
421
|
+
type ModelRequest = {
|
|
422
|
+
system?: string;
|
|
423
|
+
messages: AgentMessage[];
|
|
424
|
+
tools: ToolSpec[];
|
|
425
|
+
/** Present only on the first model call of a turn. */
|
|
426
|
+
attachments?: File[];
|
|
427
|
+
};
|
|
428
|
+
/** A streamed event from the `callModel` adapter. */
|
|
429
|
+
type ModelStreamEvent = {
|
|
430
|
+
type: "text";
|
|
431
|
+
delta: string;
|
|
432
|
+
} | {
|
|
433
|
+
type: "reasoning";
|
|
434
|
+
delta: string;
|
|
435
|
+
} | {
|
|
436
|
+
type: "tool_call";
|
|
437
|
+
toolCall: ToolCall;
|
|
438
|
+
}
|
|
439
|
+
/** Opaque provider-native representation of the assistant turn, for replay. */
|
|
440
|
+
| {
|
|
441
|
+
type: "raw";
|
|
442
|
+
raw: unknown;
|
|
443
|
+
};
|
|
444
|
+
/** The one function an engineer implements per provider. */
|
|
445
|
+
type CallModel = (req: ModelRequest) => AsyncIterable<ModelStreamEvent>;
|
|
446
|
+
/** Result of executing a custom tool — fed back to the model. */
|
|
447
|
+
type ToolResult = {
|
|
448
|
+
content: string;
|
|
449
|
+
};
|
|
450
|
+
/** A custom tool the engineer registers alongside the built-ins. */
|
|
451
|
+
type AgentTool = {
|
|
452
|
+
spec: ToolSpec;
|
|
453
|
+
execute: (input: unknown) => ToolResult | Promise<ToolResult>;
|
|
454
|
+
};
|
|
455
|
+
/** Paused-agent state, stashed while waiting for an approval answer. */
|
|
456
|
+
type AgentSnapshot = {
|
|
457
|
+
messages: AgentMessage[];
|
|
458
|
+
pendingToolCallId: string;
|
|
459
|
+
};
|
|
460
|
+
/**
|
|
461
|
+
* Where paused agent state is stored between the approval request and the
|
|
462
|
+
* user's answer. Defaults to an in-memory Map — for a server handler that
|
|
463
|
+
* spans processes, supply a Redis/db-backed implementation.
|
|
464
|
+
*/
|
|
465
|
+
type AgentSessionStore = {
|
|
466
|
+
get(id: string): AgentSnapshot | undefined | Promise<AgentSnapshot | undefined>;
|
|
467
|
+
set(id: string, snap: AgentSnapshot): void | Promise<void>;
|
|
468
|
+
delete(id: string): void | Promise<void>;
|
|
469
|
+
};
|
|
470
|
+
/** Built-in tool: render / update the inline task checklist. */
|
|
471
|
+
declare const UPDATE_TODOS_TOOL: ToolSpec;
|
|
472
|
+
/** Built-in tool: pause and ask the user to approve / choose before continuing. */
|
|
473
|
+
declare const REQUEST_APPROVAL_TOOL: ToolSpec;
|
|
474
|
+
type CreateAgentHandlerOptions = {
|
|
475
|
+
/** Provider adapter — the only provider-specific code. */
|
|
476
|
+
callModel: CallModel;
|
|
477
|
+
/** Base system prompt. Merged with any `systemPrompt` Coral injects. */
|
|
478
|
+
system?: string;
|
|
479
|
+
/** Custom tools, registered alongside the built-in update_todos / request_approval. */
|
|
480
|
+
tools?: AgentTool[];
|
|
481
|
+
/** Max tool-loop iterations per turn. Default 8. */
|
|
482
|
+
maxSteps?: number;
|
|
483
|
+
/** Where paused-agent state lives. Default: in-memory Map. */
|
|
484
|
+
sessionStore?: AgentSessionStore;
|
|
485
|
+
};
|
|
486
|
+
/**
|
|
487
|
+
* Builds a Coral `AgentHandler` that runs a provider-agnostic tool-use loop.
|
|
488
|
+
*
|
|
489
|
+
* @example
|
|
490
|
+
* <Chat onSendMessage={createAgentHandler({ callModel: claudeCallModel })} />
|
|
491
|
+
*/
|
|
492
|
+
declare function createAgentHandler(options: CreateAgentHandlerOptions): AgentHandler;
|
|
493
|
+
|
|
208
494
|
interface ChatContextValue {
|
|
209
495
|
sendMessage: (overrideInput?: string) => Promise<void>;
|
|
496
|
+
/**
|
|
497
|
+
* Re-runs the assistant turn following the matching user message.
|
|
498
|
+
* If `messageId` is omitted, regenerates the last assistant message.
|
|
499
|
+
* If `messageId` targets an assistant message, the matching user prompt is replayed.
|
|
500
|
+
* If `messageId` targets a user message, the existing assistant reply for that turn is discarded and re-generated.
|
|
501
|
+
*/
|
|
502
|
+
regenerate: (messageId?: string) => Promise<void>;
|
|
503
|
+
/**
|
|
504
|
+
* Replaces the content of an existing user message and re-runs from that point.
|
|
505
|
+
* Truncates everything after the edited message and re-invokes the handler.
|
|
506
|
+
*/
|
|
507
|
+
editMessage: (messageId: string, newContent: string) => Promise<void>;
|
|
210
508
|
scrollToBottom: () => void;
|
|
211
509
|
/** Pre-binds navigator.clipboard.writeText + the onCopy prop callback. */
|
|
212
510
|
handleCopy: (content: string) => void;
|
|
213
511
|
messages: ChatMessage[];
|
|
214
|
-
setMessages:
|
|
512
|
+
setMessages: React__default.Dispatch<React__default.SetStateAction<ChatMessage[]>>;
|
|
215
513
|
input: string;
|
|
216
|
-
setInput:
|
|
514
|
+
setInput: React__default.Dispatch<React__default.SetStateAction<string>>;
|
|
217
515
|
isTyping: boolean;
|
|
218
516
|
isRetrying: boolean;
|
|
219
517
|
isInterrupted: boolean;
|
|
220
518
|
streamingReasoning: string;
|
|
221
|
-
|
|
519
|
+
/** Name from the latest streamed `status` chunk — picks the thinking-indicator word pool. */
|
|
520
|
+
streamingStatus?: string;
|
|
222
521
|
/** Forwarded from Chat.Canvas thinkingStatus prop so Chat.Messages can read it. */
|
|
223
522
|
thinkingStatus?: string;
|
|
224
|
-
chatError: unknown | null;
|
|
225
523
|
showScrollButton: boolean;
|
|
226
524
|
/** Called by Chat.Input to report its measured height so Canvas positions the scroll button. */
|
|
227
525
|
setInputHeight: (height: number) => void;
|
|
228
|
-
messagesContainerRef:
|
|
526
|
+
messagesContainerRef: React__default.RefObject<HTMLDivElement | null>;
|
|
229
527
|
/** Called by Chat.Messages on mount/unmount so Canvas can attach scroll listener lazily. */
|
|
230
528
|
registerMessagesContainer: (el: HTMLDivElement | null) => void;
|
|
231
|
-
bottomRef:
|
|
232
|
-
lastUserInputRef:
|
|
233
|
-
hasEverSentRef:
|
|
234
|
-
shouldStopRef:
|
|
529
|
+
bottomRef: React__default.RefObject<HTMLDivElement | null>;
|
|
530
|
+
lastUserInputRef: React__default.MutableRefObject<string>;
|
|
531
|
+
hasEverSentRef: React__default.MutableRefObject<boolean>;
|
|
532
|
+
shouldStopRef: React__default.MutableRefObject<boolean>;
|
|
235
533
|
attachments: ChatAttachment[];
|
|
236
534
|
addAttachments: (files: File[]) => void;
|
|
237
535
|
removeAttachment: (id: string) => void;
|
|
536
|
+
/** Declarative list of allowed attachment kinds; renders the `+` menu in Chat.Input when set. */
|
|
537
|
+
allowedAttachments?: Array<"files" | "photos">;
|
|
538
|
+
/** Latest unanswered approval request from the assistant, or null. */
|
|
539
|
+
pendingApproval: ChatApprovalRequest | null;
|
|
540
|
+
/**
|
|
541
|
+
* Set when the user clicks an option marked `freeform: true`. While this is
|
|
542
|
+
* non-null, Chat.Input is unlocked and the next submission resolves the
|
|
543
|
+
* approval (carrying the typed text) instead of being sent as a normal turn.
|
|
544
|
+
*/
|
|
545
|
+
awaitingFreeformApproval: {
|
|
546
|
+
approvalId: string;
|
|
547
|
+
optionId: string;
|
|
548
|
+
} | null;
|
|
549
|
+
/**
|
|
550
|
+
* Resolves an approval request. If the option is `freeform`, transitions
|
|
551
|
+
* into the awaiting-freeform state instead of resolving immediately.
|
|
552
|
+
*/
|
|
553
|
+
resolveApproval: (approvalId: string, optionId: string) => void;
|
|
238
554
|
onStop?: () => void;
|
|
239
555
|
}
|
|
240
556
|
declare function useChatContext(): ChatContextValue;
|
|
241
557
|
|
|
558
|
+
/**
|
|
559
|
+
* Reads a browser `File` and returns its raw base64 payload (without the
|
|
560
|
+
* `data:<mime>;base64,` prefix).
|
|
561
|
+
*
|
|
562
|
+
* Used by Coral's built-in `api` handler to serialize attachments before
|
|
563
|
+
* POSTing them to the engineer's backend, and exported so consumers writing
|
|
564
|
+
* a custom `onSendMessage` can reuse the same encoding.
|
|
565
|
+
*/
|
|
566
|
+
declare function fileToBase64(file: File): Promise<string>;
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Built-in task vocabulary for the thinking indicator's per-task word pools.
|
|
570
|
+
*
|
|
571
|
+
* A handler streams a `{ type: "status", name }` chunk to tell the indicator
|
|
572
|
+
* which pool to cycle while it works. `name` is matched against these keys;
|
|
573
|
+
* anything unrecognized falls back to the `text` pool.
|
|
574
|
+
*
|
|
575
|
+
* - `text` — default text-only response.
|
|
576
|
+
* - `photo` — vision / image-reading responses.
|
|
577
|
+
* - `file` — document / PDF responses.
|
|
578
|
+
* - `voice` — audio transcription responses.
|
|
579
|
+
*/
|
|
580
|
+
type CoralTaskType = "text" | "photo" | "file" | "voice";
|
|
581
|
+
declare const DEFAULT_TASK_MESSAGES: Record<CoralTaskType, string[]>;
|
|
582
|
+
/**
|
|
583
|
+
* Picks the thinking-indicator word pool for a streamed status name. If `name`
|
|
584
|
+
* matches a built-in task type, its pool is used; otherwise the `text` pool is
|
|
585
|
+
* the fallback. For bespoke copy, use the `thinkingStatus` prop on `<Chat>`.
|
|
586
|
+
*/
|
|
587
|
+
declare function resolveTaskMessages(name?: string): string[];
|
|
588
|
+
|
|
589
|
+
/**
|
|
590
|
+
* A stored conversation. Consumers typically persist this shape via the
|
|
591
|
+
* adapter they pass to `ChatThreadsProvider`.
|
|
592
|
+
*/
|
|
593
|
+
interface ChatThread {
|
|
594
|
+
id: string;
|
|
595
|
+
title: string;
|
|
596
|
+
messages: ChatMessage[];
|
|
597
|
+
createdAt?: number;
|
|
598
|
+
updatedAt?: number;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Storage seam. Implement this against your backend (REST, IndexedDB,
|
|
602
|
+
* Firestore, etc.). The provider handles in-memory state so UI updates are
|
|
603
|
+
* synchronous; your adapter only needs to persist.
|
|
604
|
+
*/
|
|
605
|
+
interface ChatThreadsAdapter {
|
|
606
|
+
list(): Promise<ChatThread[]> | ChatThread[];
|
|
607
|
+
get?(id: string): Promise<ChatThread | undefined> | ChatThread | undefined;
|
|
608
|
+
create(initial?: Partial<ChatThread>): Promise<ChatThread> | ChatThread;
|
|
609
|
+
save(thread: ChatThread): Promise<void> | void;
|
|
610
|
+
rename(id: string, newTitle: string): Promise<void> | void;
|
|
611
|
+
remove(id: string): Promise<void> | void;
|
|
612
|
+
}
|
|
613
|
+
interface ChatThreadsContextValue {
|
|
614
|
+
threads: ChatThread[];
|
|
615
|
+
activeThreadId?: string;
|
|
616
|
+
activeThread?: ChatThread;
|
|
617
|
+
setActiveThreadId: (id: string | undefined) => void;
|
|
618
|
+
createThread: (initial?: Partial<ChatThread>) => Promise<ChatThread>;
|
|
619
|
+
renameThread: (id: string, newTitle: string) => Promise<void>;
|
|
620
|
+
removeThread: (id: string) => Promise<void>;
|
|
621
|
+
updateThreadMessages: (id: string, messages: ChatMessage[]) => void;
|
|
622
|
+
isLoading: boolean;
|
|
623
|
+
}
|
|
624
|
+
declare function useChatThreads(): ChatThreadsContextValue;
|
|
625
|
+
/** Default adapter — holds threads in a module-less closure. Use for demos or unit tests. */
|
|
626
|
+
declare function createMemoryThreadsAdapter(initialThreads?: ChatThread[]): ChatThreadsAdapter;
|
|
627
|
+
interface ChatThreadsProviderProps {
|
|
628
|
+
/** Storage adapter. Defaults to an in-memory adapter if omitted. */
|
|
629
|
+
adapter?: ChatThreadsAdapter;
|
|
630
|
+
/** Controlled active thread id. */
|
|
631
|
+
activeThreadId?: string;
|
|
632
|
+
/** Uncontrolled initial active thread id. */
|
|
633
|
+
defaultActiveThreadId?: string;
|
|
634
|
+
/** Fired when the active thread changes (both controlled and uncontrolled). */
|
|
635
|
+
onActiveThreadChange?: (id: string | undefined) => void;
|
|
636
|
+
children?: React.ReactNode;
|
|
637
|
+
}
|
|
638
|
+
declare function ChatThreadsProvider({ adapter: providedAdapter, activeThreadId: controlledId, defaultActiveThreadId, onActiveThreadChange, children, }: ChatThreadsProviderProps): react_jsx_runtime.JSX.Element;
|
|
639
|
+
|
|
242
640
|
declare const Chat: typeof Chat$1 & {
|
|
243
641
|
Canvas: typeof ChatCanvas;
|
|
244
642
|
Messages: typeof ChatMessages;
|
|
245
643
|
Input: typeof ChatInput;
|
|
246
644
|
Error: typeof ChatError;
|
|
247
645
|
Callout: typeof ChatCallout;
|
|
646
|
+
Approval: typeof ChatApproval;
|
|
647
|
+
TodoList: typeof ChatTodoList;
|
|
648
|
+
AttachButton: typeof ChatAttachButton;
|
|
649
|
+
ThinkingIndicator: typeof ThinkingIndicator;
|
|
248
650
|
};
|
|
249
651
|
declare const normalizeChatError: typeof normalizeChatError$1;
|
|
250
652
|
declare const createHandler: typeof createHandler$1;
|
|
251
653
|
|
|
252
|
-
export { type
|
|
654
|
+
export { type AgentHandler, type AgentMessage, type AgentSessionStore, type AgentSnapshot, type AgentTool, type ApprovalOption, type CallModel, Chat, type ChatApprovalProps, type ChatApprovalRequest, type ChatAttachButtonProps, type ChatAttachType, type ChatAttachment, type ChatCanvasProps, type ChatChunk, type ChatComponents, type ChatErrorProps, type ChatInputProps, type ChatMessage, type ChatMessageRendererProps, type ChatMessagesProps, type ChatResponse, type ChatThread, type ChatThreadsAdapter, type ChatThreadsContextValue, ChatThreadsProvider, type ChatThreadsProviderProps, type ChatTodo, type ChatTodoListProps, type CoralTaskType, type CreateAgentHandlerOptions, DEFAULT_TASK_MESSAGES, type ErrorCategory, type ModelRequest, type ModelStreamEvent, type NormalizedChatError, REQUEST_APPROVAL_TOOL, type ToolCall, type ToolResult, type ToolSpec, UPDATE_TODOS_TOOL, createAgentHandler, createHandler, createMemoryThreadsAdapter, fileToBase64, normalizeChatError, resolveTaskMessages, useChatContext, useChatThreads };
|