@gram-ai/elements 1.18.4 → 1.18.6
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/dist/components/Chat/stories/Sidecar.stories.d.ts +6 -0
- package/dist/elements.cjs +23 -22
- package/dist/elements.cjs.map +1 -0
- package/dist/elements.js +609 -599
- package/dist/elements.js.map +1 -0
- package/dist/index-Bj7jPiuy.cjs +1 -0
- package/dist/index-Bj7jPiuy.cjs.map +1 -0
- package/dist/index-CJRypLIa.js +1 -0
- package/dist/index-CJRypLIa.js.map +1 -0
- package/dist/lib/api.d.ts +2 -0
- package/dist/lib/api.test.d.ts +1 -0
- package/dist/plugins.cjs +1 -0
- package/dist/plugins.cjs.map +1 -0
- package/dist/plugins.js +1 -0
- package/dist/plugins.js.map +1 -0
- package/dist/server.cjs +1 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -0
- package/package.json +6 -2
- package/src/components/Chat/index.tsx +21 -0
- package/src/components/Chat/stories/ColorScheme.stories.tsx +52 -0
- package/src/components/Chat/stories/Composer.stories.tsx +42 -0
- package/src/components/Chat/stories/Customization.stories.tsx +88 -0
- package/src/components/Chat/stories/Density.stories.tsx +52 -0
- package/src/components/Chat/stories/FrontendTools.stories.tsx +145 -0
- package/src/components/Chat/stories/Modal.stories.tsx +84 -0
- package/src/components/Chat/stories/Model.stories.tsx +32 -0
- package/src/components/Chat/stories/Plugins.stories.tsx +50 -0
- package/src/components/Chat/stories/Radius.stories.tsx +52 -0
- package/src/components/Chat/stories/Sidecar.stories.tsx +27 -0
- package/src/components/Chat/stories/ToolApproval.stories.tsx +110 -0
- package/src/components/Chat/stories/Tools.stories.tsx +175 -0
- package/src/components/Chat/stories/Variants.stories.tsx +46 -0
- package/src/components/Chat/stories/Welcome.stories.tsx +42 -0
- package/src/components/FrontendTools/index.tsx +9 -0
- package/src/components/assistant-ui/assistant-modal.tsx +255 -0
- package/src/components/assistant-ui/assistant-sidecar.tsx +88 -0
- package/src/components/assistant-ui/attachment.tsx +233 -0
- package/src/components/assistant-ui/markdown-text.tsx +240 -0
- package/src/components/assistant-ui/reasoning.tsx +261 -0
- package/src/components/assistant-ui/thread-list.tsx +97 -0
- package/src/components/assistant-ui/thread.tsx +632 -0
- package/src/components/assistant-ui/tool-fallback.tsx +111 -0
- package/src/components/assistant-ui/tool-group.tsx +59 -0
- package/src/components/assistant-ui/tooltip-icon-button.tsx +57 -0
- package/src/components/ui/avatar.tsx +51 -0
- package/src/components/ui/button.tsx +27 -0
- package/src/components/ui/buttonVariants.ts +33 -0
- package/src/components/ui/collapsible.tsx +31 -0
- package/src/components/ui/dialog.tsx +141 -0
- package/src/components/ui/popover.tsx +46 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/tool-ui.stories.tsx +146 -0
- package/src/components/ui/tool-ui.tsx +676 -0
- package/src/components/ui/tooltip.tsx +61 -0
- package/src/contexts/ElementsProvider.tsx +256 -0
- package/src/contexts/ToolApprovalContext.tsx +120 -0
- package/src/contexts/contexts.ts +10 -0
- package/src/global.css +136 -0
- package/src/hooks/useAuth.ts +71 -0
- package/src/hooks/useDensity.ts +110 -0
- package/src/hooks/useElements.ts +14 -0
- package/src/hooks/useExpanded.ts +20 -0
- package/src/hooks/useMCPTools.ts +73 -0
- package/src/hooks/usePluginComponents.ts +34 -0
- package/src/hooks/useRadius.ts +42 -0
- package/src/hooks/useSession.ts +38 -0
- package/src/hooks/useThemeProps.ts +24 -0
- package/src/hooks/useToolApproval.ts +16 -0
- package/src/index.ts +45 -0
- package/src/lib/api.test.ts +90 -0
- package/src/lib/api.ts +8 -0
- package/src/lib/auth.ts +10 -0
- package/src/lib/easing.ts +1 -0
- package/src/lib/humanize.ts +14 -0
- package/src/lib/models.ts +22 -0
- package/src/lib/tools.ts +210 -0
- package/src/lib/utils.ts +16 -0
- package/src/plugins/README.md +49 -0
- package/src/plugins/chart/component.tsx +102 -0
- package/src/plugins/chart/index.ts +27 -0
- package/src/plugins/index.ts +7 -0
- package/src/server.ts +89 -0
- package/src/types/index.ts +726 -0
- package/src/types/plugins.ts +65 -0
- package/src/vite-env.d.ts +12 -0
|
@@ -0,0 +1,726 @@
|
|
|
1
|
+
import { MODELS } from '@/lib/models'
|
|
2
|
+
import {
|
|
3
|
+
AssistantTool,
|
|
4
|
+
ImageMessagePartComponent,
|
|
5
|
+
ReasoningGroupComponent,
|
|
6
|
+
ReasoningMessagePartComponent,
|
|
7
|
+
TextMessagePartComponent,
|
|
8
|
+
ToolCallMessagePartComponent,
|
|
9
|
+
} from '@assistant-ui/react'
|
|
10
|
+
import { LanguageModel } from 'ai'
|
|
11
|
+
import {
|
|
12
|
+
ComponentType,
|
|
13
|
+
Dispatch,
|
|
14
|
+
PropsWithChildren,
|
|
15
|
+
SetStateAction,
|
|
16
|
+
type ReactNode,
|
|
17
|
+
} from 'react'
|
|
18
|
+
import type { Plugin } from './plugins'
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Function to retrieve the session token from the backend endpoint.
|
|
22
|
+
* Override this if you have mounted your session endpoint at a different path.
|
|
23
|
+
*/
|
|
24
|
+
export type GetSessionFn = (init: { projectSlug: string }) => Promise<string>
|
|
25
|
+
|
|
26
|
+
type ServerUrl = string
|
|
27
|
+
|
|
28
|
+
export const VARIANTS = ['widget', 'sidecar', 'standalone'] as const
|
|
29
|
+
export type Variant = (typeof VARIANTS)[number]
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The top level configuration object for the Elements library.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const config: ElementsConfig = {
|
|
36
|
+
* mcp: 'https://app.getgram.ai/mcp/your-mcp-slug',
|
|
37
|
+
* projectSlug: 'my-project',
|
|
38
|
+
* systemPrompt: 'You are a helpful assistant.',
|
|
39
|
+
* }
|
|
40
|
+
*/
|
|
41
|
+
export interface ElementsConfig {
|
|
42
|
+
/**
|
|
43
|
+
* The system prompt to use for the Elements library.
|
|
44
|
+
*/
|
|
45
|
+
systemPrompt?: string
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Any plugins to use for the Elements library.
|
|
49
|
+
*
|
|
50
|
+
* @default import { recommended } from '@gram-ai/elements/plugins'
|
|
51
|
+
*/
|
|
52
|
+
plugins?: Plugin[]
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Override the default components used by the Elements library.
|
|
56
|
+
*
|
|
57
|
+
* The available components are:
|
|
58
|
+
* - Composer
|
|
59
|
+
* - UserMessage
|
|
60
|
+
* - EditComposer
|
|
61
|
+
* - AssistantMessage
|
|
62
|
+
* - ThreadWelcome
|
|
63
|
+
* - Text
|
|
64
|
+
* - Image
|
|
65
|
+
* - ToolFallback
|
|
66
|
+
* - Reasoning
|
|
67
|
+
* - ReasoningGroup
|
|
68
|
+
* - ToolGroup
|
|
69
|
+
*
|
|
70
|
+
* To understand how to override these components, please consult the [assistant-ui documentation](https://www.assistant-ui.com/docs).
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* const config: ElementsConfig = {
|
|
74
|
+
* components: {
|
|
75
|
+
* Composer: CustomComposerComponent,
|
|
76
|
+
* },
|
|
77
|
+
* }
|
|
78
|
+
*/
|
|
79
|
+
components?: ComponentOverrides
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The project slug to use for the Elements library.
|
|
83
|
+
*
|
|
84
|
+
* Your project slug can be found within the Gram dashboard.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* const config: ElementsConfig = {
|
|
88
|
+
* projectSlug: 'your-project-slug',
|
|
89
|
+
* }
|
|
90
|
+
*/
|
|
91
|
+
projectSlug: string
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The Gram Server URL to use for the Elements library.
|
|
95
|
+
* Can be retrieved from https://app.getgram.ai/{team}/{project}/mcp/{mcp_slug}
|
|
96
|
+
*
|
|
97
|
+
* Note: This config option will likely change in the future
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const config: ElementsConfig = {
|
|
101
|
+
* mcp: 'https://app.getgram.ai/mcp/your-mcp-slug',
|
|
102
|
+
* }
|
|
103
|
+
*/
|
|
104
|
+
mcp?: ServerUrl
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Custom environment variable overrides for the Elements library.
|
|
108
|
+
* Will be used to override the environment variables for the MCP server.
|
|
109
|
+
*
|
|
110
|
+
* For more documentation on passing through different kinds of environment variables, including bearer tokens, see the [Gram documentation](https://www.speakeasy.com/docs/gram/host-mcp/public-private-servers#pass-through-authentication).
|
|
111
|
+
*/
|
|
112
|
+
environment?: Record<string, unknown>
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The layout variant for the chat interface.
|
|
116
|
+
*
|
|
117
|
+
* - `widget`: A popup modal anchored to the bottom-right corner (default)
|
|
118
|
+
* - `sidecar`: A side panel that slides in from the right edge of the screen
|
|
119
|
+
* - `standalone`: A full-page chat experience
|
|
120
|
+
*
|
|
121
|
+
* @default 'widget'
|
|
122
|
+
*/
|
|
123
|
+
variant?: Variant
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* LLM model configuration.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const config: ElementsConfig = {
|
|
130
|
+
* model: {
|
|
131
|
+
* defaultModel: 'openai/gpt-4o',
|
|
132
|
+
* showModelPicker: true,
|
|
133
|
+
* },
|
|
134
|
+
* }
|
|
135
|
+
*/
|
|
136
|
+
model?: ModelConfig
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Visual appearance configuration options.
|
|
140
|
+
* Similar to OpenAI ChatKit's ThemeOption.\
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* const config: ElementsConfig = {
|
|
144
|
+
* theme: {
|
|
145
|
+
* colorScheme: 'dark',
|
|
146
|
+
* density: 'compact',
|
|
147
|
+
* radius: 'round',
|
|
148
|
+
* },
|
|
149
|
+
* }
|
|
150
|
+
*/
|
|
151
|
+
theme?: ThemeConfig
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* The configuration for the welcome message and initial suggestions.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* const config: ElementsConfig = {
|
|
158
|
+
* welcome: {
|
|
159
|
+
* title: 'Welcome to the chat',
|
|
160
|
+
* subtitle: 'This is a chat with a bot',
|
|
161
|
+
* suggestions: [
|
|
162
|
+
* { title: 'Suggestion 1', label: 'Suggestion 1', action: 'action1' },
|
|
163
|
+
* ],
|
|
164
|
+
* },
|
|
165
|
+
* }
|
|
166
|
+
*/
|
|
167
|
+
welcome?: WelcomeConfig
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* The configuration for the composer.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* const config: ElementsConfig = {
|
|
174
|
+
* composer: {
|
|
175
|
+
* placeholder: 'Enter your message...',
|
|
176
|
+
* },
|
|
177
|
+
* }
|
|
178
|
+
*/
|
|
179
|
+
composer?: ComposerConfig
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Optional property to override the LLM provider. If you override the model,
|
|
183
|
+
* then logs & usage metrics will not be tracked directly via Gram.
|
|
184
|
+
*
|
|
185
|
+
* Please ensure that you are using an AI SDK v2 compatible model (e.g a
|
|
186
|
+
* Vercel AI sdk provider in the v2 semver range), as this is the only variant
|
|
187
|
+
* compatible with AI SDK V5
|
|
188
|
+
*
|
|
189
|
+
* Example with Google Gemini:
|
|
190
|
+
* ```ts
|
|
191
|
+
* import { google } from '@ai-sdk/google';
|
|
192
|
+
*
|
|
193
|
+
* const googleGemini = google('gemini-3-pro-preview');
|
|
194
|
+
*
|
|
195
|
+
* const config: ElementsConfig = {
|
|
196
|
+
* {other options}
|
|
197
|
+
* languageModel: googleGemini,
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
languageModel?: LanguageModel
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* The configuration for the modal window.
|
|
205
|
+
* Only applicable if variant is 'widget'.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* const config: ElementsConfig = {
|
|
209
|
+
* modal: {
|
|
210
|
+
* title: 'Chat',
|
|
211
|
+
* position: 'bottom-right',
|
|
212
|
+
* expandable: true,
|
|
213
|
+
* defaultExpanded: false,
|
|
214
|
+
* dimensions: {
|
|
215
|
+
* default: {
|
|
216
|
+
* width: 400,
|
|
217
|
+
* height: 600,
|
|
218
|
+
* },
|
|
219
|
+
* },
|
|
220
|
+
* },
|
|
221
|
+
* }
|
|
222
|
+
*/
|
|
223
|
+
modal?: ModalConfig
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* The configuration for the sidecar panel.
|
|
227
|
+
* Only applies if variant is 'sidecar'.
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* const config: ElementsConfig = {
|
|
231
|
+
* sidecar: {
|
|
232
|
+
* title: 'Chat',
|
|
233
|
+
* expandable: true,
|
|
234
|
+
* defaultExpanded: false,
|
|
235
|
+
* dimensions: {
|
|
236
|
+
* default: {
|
|
237
|
+
* width: 400,
|
|
238
|
+
* height: 600,
|
|
239
|
+
* },
|
|
240
|
+
* },
|
|
241
|
+
* },
|
|
242
|
+
* }
|
|
243
|
+
*/
|
|
244
|
+
sidecar?: SidecarConfig
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* The configuration for the tools.
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* const config: ElementsConfig = {
|
|
251
|
+
* tools: {
|
|
252
|
+
* expandToolGroupsByDefault: true,
|
|
253
|
+
* frontendTools: {
|
|
254
|
+
* fetchUrl: FetchTool,
|
|
255
|
+
* },
|
|
256
|
+
* components: {
|
|
257
|
+
* fetchUrl: FetchToolComponent,
|
|
258
|
+
* },
|
|
259
|
+
* },
|
|
260
|
+
* }
|
|
261
|
+
*/
|
|
262
|
+
tools?: ToolsConfig
|
|
263
|
+
|
|
264
|
+
api?: {
|
|
265
|
+
/**
|
|
266
|
+
* The Gram API URL to use for the Elements library.
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* const config: ElementsConfig = {
|
|
270
|
+
* apiURL: 'https://api.getgram.ai',
|
|
271
|
+
* }
|
|
272
|
+
*/
|
|
273
|
+
url?: string
|
|
274
|
+
} & AuthConfig
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export type SessionAuthConfig = {
|
|
278
|
+
/**
|
|
279
|
+
* The function to use to retrieve the session token from the backend endpoint.
|
|
280
|
+
* By default, this will attempt to fetch the session token from `/chat/session`.
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* const config: ElementsConfig = {
|
|
284
|
+
* api: {
|
|
285
|
+
* sessionFn: async () => {
|
|
286
|
+
* return fetch('/chat/session').then(res => res.json()).then(data => data.client_token)
|
|
287
|
+
* },
|
|
288
|
+
* },
|
|
289
|
+
* }
|
|
290
|
+
*/
|
|
291
|
+
sessionFn: GetSessionFn
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* The API key auth config is used to authenticate the Elements library using an API key only.
|
|
296
|
+
*
|
|
297
|
+
* NOTE: This is not recommended for production use, and a warning
|
|
298
|
+
* will be displayed in the chat interface if you use this config.
|
|
299
|
+
* Define a session endpoint instead to avoid this warning.
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* const config: ElementsConfig = {
|
|
303
|
+
* api: {
|
|
304
|
+
* UNSAFE_apiKey: 'your-api-key',
|
|
305
|
+
* },
|
|
306
|
+
* }
|
|
307
|
+
*/
|
|
308
|
+
export type ApiKeyAuthConfig = {
|
|
309
|
+
/**
|
|
310
|
+
* The API key to use if you haven't yet configured a session endpoint.
|
|
311
|
+
* Do not use this in production.
|
|
312
|
+
*
|
|
313
|
+
* @example
|
|
314
|
+
* const config: ElementsConfig = {
|
|
315
|
+
* api: {
|
|
316
|
+
* UNSAFE_apiKey: 'your-api-key',
|
|
317
|
+
* },
|
|
318
|
+
* }
|
|
319
|
+
*/
|
|
320
|
+
UNSAFE_apiKey: string
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export type AuthConfig = SessionAuthConfig | ApiKeyAuthConfig | undefined
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* The LLM model to use for the Elements library.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* const config: ElementsConfig = {
|
|
330
|
+
* model: {
|
|
331
|
+
* defaultModel: 'openai/gpt-4o',
|
|
332
|
+
* },
|
|
333
|
+
* }
|
|
334
|
+
*/
|
|
335
|
+
export type Model = (typeof MODELS)[number]
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* ModelConfig is used to configure model support in the Elements library.
|
|
339
|
+
*
|
|
340
|
+
*/
|
|
341
|
+
export interface ModelConfig {
|
|
342
|
+
/**
|
|
343
|
+
* Whether to show the model picker in the composer.
|
|
344
|
+
*/
|
|
345
|
+
showModelPicker?: boolean
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* The default model to use for the Elements library.
|
|
349
|
+
*/
|
|
350
|
+
defaultModel?: Model
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export const DENSITIES = ['compact', 'normal', 'spacious'] as const
|
|
354
|
+
export type Density = (typeof DENSITIES)[number]
|
|
355
|
+
export const COLOR_SCHEMES = ['light', 'dark', 'system'] as const
|
|
356
|
+
export type ColorScheme = (typeof COLOR_SCHEMES)[number]
|
|
357
|
+
|
|
358
|
+
export const RADII = ['round', 'soft', 'sharp'] as const
|
|
359
|
+
export type Radius = (typeof RADII)[number]
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* ThemeConfig provides visual appearance customization options.
|
|
363
|
+
* Inspired by OpenAI ChatKit's ThemeOption.
|
|
364
|
+
*
|
|
365
|
+
* @example
|
|
366
|
+
* const config: ElementsConfig = {
|
|
367
|
+
* theme: {
|
|
368
|
+
* colorScheme: 'dark',
|
|
369
|
+
* density: 'compact',
|
|
370
|
+
* radius: 'round',
|
|
371
|
+
* },
|
|
372
|
+
* }
|
|
373
|
+
*/
|
|
374
|
+
export interface ThemeConfig {
|
|
375
|
+
/**
|
|
376
|
+
* The color scheme to use for the UI.
|
|
377
|
+
* @default 'light'
|
|
378
|
+
*/
|
|
379
|
+
colorScheme?: ColorScheme
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Determines the overall spacing of the UI.
|
|
383
|
+
* - `compact`: Reduced padding and margins for dense layouts
|
|
384
|
+
* - `normal`: Standard spacing (default)
|
|
385
|
+
* - `spacious`: Increased padding and margins for airy layouts
|
|
386
|
+
* @default 'normal'
|
|
387
|
+
*/
|
|
388
|
+
density?: Density
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Determines the overall roundness of the UI.
|
|
392
|
+
* - `round`: Large border radius
|
|
393
|
+
* - `soft`: Moderate border radius (default)
|
|
394
|
+
* - `sharp`: Minimal border radius
|
|
395
|
+
* @default 'soft'
|
|
396
|
+
*/
|
|
397
|
+
radius?: Radius
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export interface ComponentOverrides {
|
|
401
|
+
/**
|
|
402
|
+
* The component to use for the composer (the input area where users type messages)
|
|
403
|
+
*/
|
|
404
|
+
Composer?: ComponentType
|
|
405
|
+
/**
|
|
406
|
+
* The component to use for the user message.
|
|
407
|
+
*/
|
|
408
|
+
UserMessage?: ComponentType
|
|
409
|
+
/**
|
|
410
|
+
* The component to use for the edit composer (inline message editor)
|
|
411
|
+
*/
|
|
412
|
+
EditComposer?: ComponentType
|
|
413
|
+
/**
|
|
414
|
+
* The component to use for the assistant message (messages generated by the LLM).
|
|
415
|
+
*
|
|
416
|
+
* Note: if you override this, the Text component will not be used.
|
|
417
|
+
*/
|
|
418
|
+
AssistantMessage?: ComponentType
|
|
419
|
+
/**
|
|
420
|
+
* The component to use for the thread welcome.
|
|
421
|
+
*/
|
|
422
|
+
ThreadWelcome?: ComponentType
|
|
423
|
+
|
|
424
|
+
// MessagePrimitive.Parts components
|
|
425
|
+
/**
|
|
426
|
+
* The component to use for the text message.
|
|
427
|
+
*/
|
|
428
|
+
Text?: TextMessagePartComponent
|
|
429
|
+
/**
|
|
430
|
+
* The component to use for the image message.
|
|
431
|
+
*/
|
|
432
|
+
Image?: ImageMessagePartComponent
|
|
433
|
+
/**
|
|
434
|
+
* The component to use for the tool fallback (default UI shown when a tool returns a result).
|
|
435
|
+
*/
|
|
436
|
+
ToolFallback?: ToolCallMessagePartComponent
|
|
437
|
+
/**
|
|
438
|
+
* The component to use for the reasoning message.
|
|
439
|
+
*/
|
|
440
|
+
Reasoning?: ReasoningMessagePartComponent
|
|
441
|
+
/**
|
|
442
|
+
* The component to use for the reasoning group.
|
|
443
|
+
*/
|
|
444
|
+
ReasoningGroup?: ReasoningGroupComponent
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* The component to use for the tool group (a group of tool calls returned by the LLM in a single message).
|
|
448
|
+
*/
|
|
449
|
+
ToolGroup?: ComponentType<
|
|
450
|
+
PropsWithChildren<{ startIndex: number; endIndex: number }>
|
|
451
|
+
>
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* ToolsConfig is used to configure tool support in the Elements library.
|
|
456
|
+
* At the moment, you can override the default React components used by
|
|
457
|
+
* individual tool results.
|
|
458
|
+
*
|
|
459
|
+
* @example
|
|
460
|
+
* const config: ElementsConfig = {
|
|
461
|
+
* tools: {
|
|
462
|
+
* components: {
|
|
463
|
+
* "get_current_weather": WeatherComponent,
|
|
464
|
+
* },
|
|
465
|
+
* },
|
|
466
|
+
* }
|
|
467
|
+
*/
|
|
468
|
+
|
|
469
|
+
export interface ToolsConfig {
|
|
470
|
+
/**
|
|
471
|
+
* Whether individual tool calls within a group should be expanded by default.
|
|
472
|
+
* @default false
|
|
473
|
+
*/
|
|
474
|
+
expandToolGroupsByDefault?: boolean
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* `components` can be used to override the default components used by the
|
|
478
|
+
* Elements library for a given tool result.
|
|
479
|
+
*
|
|
480
|
+
* Please ensure that the tool name directly matches the tool name in your Gram toolset.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* const config: ElementsConfig = {
|
|
484
|
+
* tools: {
|
|
485
|
+
* components: {
|
|
486
|
+
* "get_current_weather": WeatherComponent,
|
|
487
|
+
* },
|
|
488
|
+
* },
|
|
489
|
+
* }
|
|
490
|
+
*/
|
|
491
|
+
components?:
|
|
492
|
+
| Record<string, ToolCallMessagePartComponent | undefined>
|
|
493
|
+
| undefined
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* The frontend tools to use for the Elements library.
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* ```ts
|
|
500
|
+
* import { defineFrontendTool } from '@gram-ai/elements'
|
|
501
|
+
*
|
|
502
|
+
* const FetchTool = defineFrontendTool<{ url: string }, string>(
|
|
503
|
+
* {
|
|
504
|
+
* description: 'Fetch a URL (supports CORS-enabled URLs like httpbin.org)',
|
|
505
|
+
* parameters: z.object({
|
|
506
|
+
* url: z.string().describe('URL to fetch (must support CORS)'),
|
|
507
|
+
* }),
|
|
508
|
+
* execute: async ({ url }) => {
|
|
509
|
+
* const response = await fetch(url as string)
|
|
510
|
+
* const text = await response.text()
|
|
511
|
+
* return text
|
|
512
|
+
* },
|
|
513
|
+
* },
|
|
514
|
+
* 'fetchUrl'
|
|
515
|
+
* )
|
|
516
|
+
* const config: ElementsConfig = {
|
|
517
|
+
* tools: {
|
|
518
|
+
* frontendTools: {
|
|
519
|
+
* fetchUrl: FetchTool,
|
|
520
|
+
* },
|
|
521
|
+
* },
|
|
522
|
+
* }
|
|
523
|
+
* ```
|
|
524
|
+
*
|
|
525
|
+
* You can also override the default components used by the
|
|
526
|
+
* Elements library for a given tool result.
|
|
527
|
+
*
|
|
528
|
+
* @example
|
|
529
|
+
* ```ts
|
|
530
|
+
* import { FetchToolComponent } from './components/FetchToolComponent'
|
|
531
|
+
*
|
|
532
|
+
* const config: ElementsConfig = {
|
|
533
|
+
* tools: {
|
|
534
|
+
* frontendTools: {
|
|
535
|
+
* fetchUrl: FetchTool,
|
|
536
|
+
* },
|
|
537
|
+
* components: {
|
|
538
|
+
* 'fetchUrl': FetchToolComponent, // will override the default component used by the Elements library for the 'fetchUrl' tool
|
|
539
|
+
* },
|
|
540
|
+
* },
|
|
541
|
+
* }
|
|
542
|
+
* ```
|
|
543
|
+
*/
|
|
544
|
+
frontendTools?: Record<string, AssistantTool>
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* List of tool names that require confirmation from the end user before
|
|
548
|
+
* being executed. The user can choose to approve once or approve for the
|
|
549
|
+
* entire session via the UI.
|
|
550
|
+
*
|
|
551
|
+
* @example
|
|
552
|
+
* ```ts
|
|
553
|
+
* tools: {
|
|
554
|
+
* toolsRequiringApproval: ['delete_file', 'send_email'],
|
|
555
|
+
* }
|
|
556
|
+
* ```
|
|
557
|
+
*/
|
|
558
|
+
toolsRequiringApproval?: string[]
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
export interface WelcomeConfig {
|
|
562
|
+
/**
|
|
563
|
+
* The welcome message to display when the thread is empty.
|
|
564
|
+
*/
|
|
565
|
+
title: string
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* The subtitle to display when the thread is empty.
|
|
569
|
+
*/
|
|
570
|
+
subtitle: string
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* The suggestions to display when the thread is empty.
|
|
574
|
+
*/
|
|
575
|
+
suggestions?: Suggestion[]
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
export interface Suggestion {
|
|
579
|
+
title: string
|
|
580
|
+
label: string
|
|
581
|
+
action: string
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
export interface Dimensions {
|
|
585
|
+
default: Dimension
|
|
586
|
+
expanded?: {
|
|
587
|
+
width: number | string
|
|
588
|
+
height: number | string
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
export interface Dimension {
|
|
593
|
+
width: number | string
|
|
594
|
+
height: number | string
|
|
595
|
+
maxHeight?: number | string
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
interface ExpandableConfig {
|
|
599
|
+
/**
|
|
600
|
+
* Whether the modal or sidecar can be expanded
|
|
601
|
+
*/
|
|
602
|
+
expandable?: boolean
|
|
603
|
+
|
|
604
|
+
/**
|
|
605
|
+
* Whether the modal or sidecar should be expanded by default.
|
|
606
|
+
* @default false
|
|
607
|
+
*/
|
|
608
|
+
defaultExpanded?: boolean
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* The dimensions for the modal or sidecar window.
|
|
612
|
+
*/
|
|
613
|
+
dimensions?: Dimensions
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
export type ModalTriggerPosition =
|
|
617
|
+
| 'bottom-right'
|
|
618
|
+
| 'bottom-left'
|
|
619
|
+
| 'top-right'
|
|
620
|
+
| 'top-left'
|
|
621
|
+
|
|
622
|
+
export interface ModalConfig extends ExpandableConfig {
|
|
623
|
+
/**
|
|
624
|
+
* Whether to open the modal window by default.
|
|
625
|
+
*/
|
|
626
|
+
defaultOpen?: boolean
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* The title displayed in the modal header.
|
|
630
|
+
* @default 'Chat'
|
|
631
|
+
*/
|
|
632
|
+
title?: string
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* The position of the modal trigger
|
|
636
|
+
*
|
|
637
|
+
* @default 'bottom-right'
|
|
638
|
+
*/
|
|
639
|
+
position?: ModalTriggerPosition
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* The icon to use for the modal window.
|
|
643
|
+
* Receives the current state of the modal window.
|
|
644
|
+
*
|
|
645
|
+
* @example
|
|
646
|
+
* ```ts
|
|
647
|
+
* import { MessageCircleIcon } from 'lucide-react'
|
|
648
|
+
* import { cn } from '@/lib/utils'
|
|
649
|
+
*
|
|
650
|
+
* const config: ElementsConfig = {
|
|
651
|
+
* modal: {
|
|
652
|
+
* icon: (state) => {
|
|
653
|
+
* return <div className={cn('size-6', state === 'open' ? 'rotate-90' : 'rotate-0')}>
|
|
654
|
+
* <MessageCircleIcon className="size-6" />
|
|
655
|
+
* </div>
|
|
656
|
+
* },
|
|
657
|
+
* },
|
|
658
|
+
* }
|
|
659
|
+
* ```
|
|
660
|
+
*/
|
|
661
|
+
icon?: (state: 'open' | 'closed' | undefined) => ReactNode
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
export interface ComposerConfig {
|
|
665
|
+
/**
|
|
666
|
+
* The placeholder text for the composer input.
|
|
667
|
+
* @default 'Send a message...'
|
|
668
|
+
*/
|
|
669
|
+
placeholder?: string
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Configuration for file attachments in the composer.
|
|
673
|
+
* Set to `false` to disable attachments entirely.
|
|
674
|
+
* Set to `true` for default attachment behavior.
|
|
675
|
+
* Or provide an object for fine-grained control.
|
|
676
|
+
* @default true
|
|
677
|
+
*/
|
|
678
|
+
attachments?: boolean | AttachmentsConfig
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* AttachmentsConfig provides fine-grained control over file attachments.
|
|
683
|
+
*
|
|
684
|
+
* Note: not yet implemented. Attachments are not supported yet.
|
|
685
|
+
*/
|
|
686
|
+
export interface AttachmentsConfig {
|
|
687
|
+
/**
|
|
688
|
+
* Accepted file types. Can be MIME types or file extensions.
|
|
689
|
+
* @example ['image/*', '.pdf', '.docx']
|
|
690
|
+
*/
|
|
691
|
+
accept?: string[]
|
|
692
|
+
|
|
693
|
+
/**
|
|
694
|
+
* Maximum number of files that can be attached at once.
|
|
695
|
+
* @default 10
|
|
696
|
+
*/
|
|
697
|
+
maxCount?: number
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Maximum file size in bytes.
|
|
701
|
+
* @default 104857600 (100MB)
|
|
702
|
+
*/
|
|
703
|
+
maxSize?: number
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
export interface SidecarConfig extends ExpandableConfig {
|
|
707
|
+
/**
|
|
708
|
+
* The title displayed in the sidecar header.
|
|
709
|
+
* @default 'Chat'
|
|
710
|
+
*/
|
|
711
|
+
title?: string
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* @internal
|
|
716
|
+
*/
|
|
717
|
+
export type ElementsContextType = {
|
|
718
|
+
config: ElementsConfig
|
|
719
|
+
setModel: (model: Model) => void
|
|
720
|
+
model: Model
|
|
721
|
+
isExpanded: boolean
|
|
722
|
+
setIsExpanded: Dispatch<SetStateAction<boolean>>
|
|
723
|
+
isOpen: boolean
|
|
724
|
+
setIsOpen: (isOpen: boolean) => void
|
|
725
|
+
plugins: Plugin[]
|
|
726
|
+
}
|