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