@gram-ai/elements 1.33.2 → 1.35.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/dist/compat-shims-CO9JXXV4.cjs.map +1 -1
- package/dist/compat-shims-DxtUrORi.js.map +1 -1
- package/dist/compat-shims.d.ts +9 -8
- package/dist/components/Chat/index.d.ts +2 -1
- package/dist/components/ChatHistory.d.ts +1 -1
- package/dist/components/FrontendTools/index.d.ts +1 -1
- package/dist/components/Replay.d.ts +1 -1
- package/dist/components/Replay.stories.d.ts +2 -2
- package/dist/components/ShadowRoot.d.ts +1 -1
- package/dist/components/ShareButton/index.d.ts +1 -1
- package/dist/components/ui/avatar.d.ts +3 -3
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/buttonVariants.d.ts +2 -2
- package/dist/components/ui/calendar.d.ts +2 -1
- package/dist/components/ui/collapsible.d.ts +3 -3
- package/dist/components/ui/dialog.d.ts +10 -10
- package/dist/components/ui/popover.d.ts +4 -4
- package/dist/components/ui/skeleton.d.ts +1 -1
- package/dist/components/ui/time-range-picker.d.ts +18 -1
- package/dist/components/ui/time-range-picker.test.d.ts +1 -0
- package/dist/components/ui/tool-ui.d.ts +7 -7
- package/dist/components/ui/tooltip.d.ts +4 -4
- package/dist/contexts/ConnectionStatusContext.d.ts +1 -1
- package/dist/contexts/ElementsProvider.d.ts +1 -1
- package/dist/contexts/ToolApprovalContext.d.ts +2 -2
- package/dist/contexts/ToolExecutionContext.d.ts +1 -1
- package/dist/contexts/portal-container.d.ts +1 -1
- package/dist/elements.cjs +1 -1
- package/dist/elements.css +1 -1
- package/dist/elements.js +19 -16
- package/dist/hooks/useDensity.d.ts +1 -1
- package/dist/hooks/useElements.d.ts +2 -1
- package/dist/hooks/useGramThreadListAdapter.d.ts +26 -0
- package/dist/hooks/useRadius.d.ts +1 -1
- package/dist/hooks/useThemeProps.d.ts +1 -1
- package/dist/hooks/useToolApproval.d.ts +2 -1
- package/dist/{index-reVrRxP1.js → index-BhIowiZF.js} +9744 -9493
- package/dist/index-BhIowiZF.js.map +1 -0
- package/dist/{index-DAWGW1Nj.cjs → index-D0jIGQr7.cjs} +43 -43
- package/dist/index-D0jIGQr7.cjs.map +1 -0
- package/dist/{index-CGoLfO5p.js → index-Dz13dSDa.js} +108 -51
- package/dist/index-Dz13dSDa.js.map +1 -0
- package/dist/index-PXd3rs95.cjs +194 -0
- package/dist/index-PXd3rs95.cjs.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/lib/errorTracking.d.ts +1 -1
- package/dist/lib/messageConverter.d.ts +58 -8
- package/dist/lib/models.d.ts +1 -1
- package/dist/lib/tools.d.ts +11 -10
- package/dist/lib/utils.d.ts +2 -0
- package/dist/plugins/generative-ui/catalog.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/accordion.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/action-button.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/alert.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/avatar-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/avatar.d.ts +6 -6
- package/dist/plugins/generative-ui/ui/badge.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/button.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/card.d.ts +7 -7
- package/dist/plugins/generative-ui/ui/checkbox-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/checkbox.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/data-table.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/dialog.d.ts +10 -10
- package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +15 -15
- package/dist/plugins/generative-ui/ui/grid.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/index.d.ts +57 -40
- package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/input.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/label.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/list.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/metric.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/pagination.d.ts +7 -7
- package/dist/plugins/generative-ui/ui/popover.d.ts +7 -7
- package/dist/plugins/generative-ui/ui/progress.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/radio-group.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/select-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/select.d.ts +10 -10
- package/dist/plugins/generative-ui/ui/separator.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/skeleton-wrapper.d.ts +2 -1
- package/dist/plugins/generative-ui/ui/skeleton.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/stack.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/switch.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/table.d.ts +8 -8
- package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/tabs.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/text.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/textarea.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/tooltip.d.ts +4 -4
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/{profiler-noho3NG9.js → profiler-CtGKTWWP.js} +2 -2
- package/dist/{profiler-noho3NG9.js.map → profiler-CtGKTWWP.js.map} +1 -1
- package/dist/{profiler-B3tfiOx4.cjs → profiler-l7_HjTyw.cjs} +2 -2
- package/dist/{profiler-B3tfiOx4.cjs.map → profiler-l7_HjTyw.cjs.map} +1 -1
- package/dist/react-shim.cjs.map +1 -1
- package/dist/react-shim.d.ts +1 -1
- package/dist/react-shim.js +1 -4
- package/dist/react-shim.js.map +1 -1
- package/dist/server/bun.cjs.map +1 -1
- package/dist/server/bun.js.map +1 -1
- package/dist/server/express.cjs.map +1 -1
- package/dist/server/express.js.map +1 -1
- package/dist/server/fastify.cjs.map +1 -1
- package/dist/server/fastify.js.map +1 -1
- package/dist/server/hono.cjs.map +1 -1
- package/dist/server/hono.js.map +1 -1
- package/dist/server/nextjs.cjs.map +1 -1
- package/dist/server/nextjs.js.map +1 -1
- package/dist/server/tanstack-start.cjs.map +1 -1
- package/dist/server/tanstack-start.js.map +1 -1
- package/dist/{startRecording-7Oy6wM18.cjs → startRecording-DEw2Aeq4.cjs} +2 -2
- package/dist/{startRecording-7Oy6wM18.cjs.map → startRecording-DEw2Aeq4.cjs.map} +1 -1
- package/dist/{startRecording-mkmig-2n.js → startRecording-iYEL0-vr.js} +2 -2
- package/dist/{startRecording-mkmig-2n.js.map → startRecording-iYEL0-vr.js.map} +1 -1
- package/dist/types/index.d.ts +93 -4
- package/package.json +8 -9
- package/src/compat-shims.ts +16 -2
- package/src/components/Chat/index.tsx +4 -1
- package/src/components/Chat/stories/FrontendTools.stories.tsx +1 -1
- package/src/components/Chat/stories/ToolApproval.stories.tsx +2 -2
- package/src/components/Chat/stories/Tools.stories.tsx +13 -5
- package/src/components/ChatHistory.tsx +3 -1
- package/src/components/FrontendTools/index.tsx +1 -1
- package/src/components/MessageContent.tsx +1 -0
- package/src/components/Replay.stories.tsx +2 -3
- package/src/components/Replay.tsx +17 -10
- package/src/components/ShadowRoot.tsx +2 -2
- package/src/components/ShareButton/index.tsx +4 -2
- package/src/components/assistant-ui/assistant-modal.tsx +5 -3
- package/src/components/assistant-ui/attachment.tsx +1 -1
- package/src/components/assistant-ui/error-boundary.tsx +1 -1
- package/src/components/assistant-ui/markdown-text.tsx +1 -1
- package/src/components/assistant-ui/thread.tsx +256 -14
- package/src/components/assistant-ui/tool-mention-autocomplete.tsx +1 -1
- package/src/components/ui/avatar.tsx +3 -3
- package/src/components/ui/calendar.tsx +1 -1
- package/src/components/ui/collapsible.tsx +7 -3
- package/src/components/ui/dialog.tsx +18 -10
- package/src/components/ui/generative-ui.tsx +9 -4
- package/src/components/ui/popover.tsx +4 -4
- package/src/components/ui/skeleton.tsx +4 -1
- package/src/components/ui/time-range-picker.stories.tsx +164 -154
- package/src/components/ui/time-range-picker.test.ts +57 -0
- package/src/components/ui/time-range-picker.tsx +40 -9
- package/src/components/ui/tool-ui.tsx +18 -9
- package/src/components/ui/tooltip.tsx +4 -4
- package/src/contexts/ChatIdContext.tsx +1 -1
- package/src/contexts/ConnectionStatusContext.tsx +6 -5
- package/src/contexts/ElementsProvider.tsx +109 -37
- package/src/contexts/ReplayContext.ts +1 -1
- package/src/contexts/ToolApprovalContext.tsx +5 -1
- package/src/contexts/ToolExecutionContext.tsx +1 -1
- package/src/contexts/portal-container.tsx +1 -1
- package/src/hooks/useAuth.ts +2 -1
- package/src/hooks/useDensity.ts +1 -1
- package/src/hooks/useElements.ts +2 -1
- package/src/hooks/useFollowOnSuggestions.ts +3 -6
- package/src/hooks/useGramThreadListAdapter.tsx +118 -9
- package/src/hooks/useMCPTools.ts +2 -2
- package/src/hooks/useModel.ts +1 -3
- package/src/hooks/usePluginComponents.ts +3 -1
- package/src/hooks/useRadius.ts +1 -1
- package/src/hooks/useSession.ts +3 -1
- package/src/hooks/useThemeProps.ts +5 -5
- package/src/hooks/useToolApproval.ts +2 -1
- package/src/index.ts +16 -0
- package/src/lib/cassette.ts +21 -27
- package/src/lib/contextCompaction.test.ts +2 -2
- package/src/lib/contextCompaction.ts +20 -8
- package/src/lib/errorTracking.ts +1 -4
- package/src/lib/messageConverter.test.ts +11 -13
- package/src/lib/messageConverter.ts +105 -58
- package/src/lib/models.ts +19 -7
- package/src/lib/token.ts +2 -5
- package/src/lib/tool-mentions.ts +5 -2
- package/src/lib/tools.byte-cap.test.ts +1 -1
- package/src/lib/tools.test.ts +1 -1
- package/src/lib/tools.ts +15 -5
- package/src/lib/utils.ts +22 -2
- package/src/lib.d.ts +8 -1
- package/src/plugins/chart/chart.test.ts +3 -4
- package/src/plugins/chart/component.tsx +7 -6
- package/src/plugins/chart/ui/area-chart.tsx +1 -1
- package/src/plugins/chart/ui/line-chart.tsx +1 -1
- package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +2 -2
- package/src/plugins/generative-ui/ui/accordion.tsx +4 -4
- package/src/plugins/generative-ui/ui/action-button.tsx +4 -2
- package/src/plugins/generative-ui/ui/alert-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/alert.tsx +7 -3
- package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +5 -1
- package/src/plugins/generative-ui/ui/avatar.tsx +12 -6
- package/src/plugins/generative-ui/ui/badge.tsx +1 -1
- package/src/plugins/generative-ui/ui/button-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/button.tsx +1 -1
- package/src/plugins/generative-ui/ui/card-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/card.tsx +28 -7
- package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/checkbox.tsx +1 -1
- package/src/plugins/generative-ui/ui/data-table.tsx +1 -1
- package/src/plugins/generative-ui/ui/dialog.tsx +15 -10
- package/src/plugins/generative-ui/ui/dropdown-menu.tsx +33 -15
- package/src/plugins/generative-ui/ui/grid.tsx +1 -1
- package/src/plugins/generative-ui/ui/index.ts +154 -40
- package/src/plugins/generative-ui/ui/input-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/input.tsx +5 -1
- package/src/plugins/generative-ui/ui/label.tsx +1 -1
- package/src/plugins/generative-ui/ui/list.tsx +5 -1
- package/src/plugins/generative-ui/ui/metric.tsx +2 -1
- package/src/plugins/generative-ui/ui/pagination.tsx +12 -7
- package/src/plugins/generative-ui/ui/popover.tsx +13 -7
- package/src/plugins/generative-ui/ui/progress.tsx +1 -1
- package/src/plugins/generative-ui/ui/radio-group.tsx +2 -2
- package/src/plugins/generative-ui/ui/select-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/select.tsx +14 -10
- package/src/plugins/generative-ui/ui/separator.tsx +1 -1
- package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +1 -1
- package/src/plugins/generative-ui/ui/skeleton.tsx +4 -1
- package/src/plugins/generative-ui/ui/stack.tsx +1 -1
- package/src/plugins/generative-ui/ui/switch.tsx +1 -1
- package/src/plugins/generative-ui/ui/table.tsx +29 -8
- package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +5 -2
- package/src/plugins/generative-ui/ui/tabs.tsx +4 -4
- package/src/plugins/generative-ui/ui/text.tsx +1 -1
- package/src/plugins/generative-ui/ui/textarea.tsx +4 -1
- package/src/plugins/generative-ui/ui/tooltip.tsx +4 -4
- package/src/react-shim.ts +9 -4
- package/src/server/bun.ts +1 -1
- package/src/server/express.ts +1 -1
- package/src/server/fastify.ts +1 -1
- package/src/server/hono.ts +1 -1
- package/src/server/nextjs.ts +1 -1
- package/src/server/tanstack-start.ts +1 -1
- package/src/storybook.d.ts +5 -0
- package/src/types/index.ts +112 -4
- package/dist/index-BCV7Zf9E.cjs +0 -194
- package/dist/index-BCV7Zf9E.cjs.map +0 -1
- package/dist/index-CGoLfO5p.js.map +0 -1
- package/dist/index-DAWGW1Nj.cjs.map +0 -1
- package/dist/index-reVrRxP1.js.map +0 -1
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { GramChatMessage } from '../lib/messageConverter';
|
|
1
2
|
import { MODELS } from '../lib/models';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { LanguageModel } from 'ai';
|
|
3
|
+
import { AssistantTool, ImageMessagePartComponent, ReasoningGroupComponent, ReasoningMessagePartComponent, TextMessagePartComponent, ToolCallMessagePartComponent } from '@assistant-ui/react';
|
|
4
|
+
import { ChatTransport, LanguageModel, UIMessage } from 'ai';
|
|
5
5
|
import { ComponentType, Dispatch, PropsWithChildren, SetStateAction, ReactNode } from 'react';
|
|
6
6
|
import { Plugin } from './plugins';
|
|
7
7
|
/**
|
|
@@ -34,6 +34,34 @@ export interface MCPServerEntry {
|
|
|
34
34
|
}
|
|
35
35
|
export declare const VARIANTS: readonly ["widget", "sidecar", "standalone"];
|
|
36
36
|
export type Variant = (typeof VARIANTS)[number];
|
|
37
|
+
/**
|
|
38
|
+
* Live chat context handed to a {@link ElementsTransportFactory}.
|
|
39
|
+
*/
|
|
40
|
+
export interface ElementsTransportContext {
|
|
41
|
+
/**
|
|
42
|
+
* The active conversation's persisted chat id, or null when the current
|
|
43
|
+
* thread has no server-side chat yet (a brand-new, not-yet-sent thread).
|
|
44
|
+
* Sourced from the thread-list runtime, so it stays current as the user
|
|
45
|
+
* switches conversations.
|
|
46
|
+
*/
|
|
47
|
+
getChatId: () => string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Adopt a chat id assigned out-of-band (e.g. a server-minted id a consumer
|
|
50
|
+
* transport receives on the first send). Call at the START of an async send
|
|
51
|
+
* to capture the active conversation, then invoke the returned function with
|
|
52
|
+
* the server's id once it's known. The closure binds to the conversation the
|
|
53
|
+
* send originated from, so a thread switch or a parallel send on another
|
|
54
|
+
* thread during the round-trip can't mis-associate the id.
|
|
55
|
+
*/
|
|
56
|
+
adoptChatId: () => (chatId: string) => void;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A factory for a {@link ChatTransport}. When `ElementsConfig.transport` is a
|
|
60
|
+
* function, Elements invokes it once inside the provider and passes the live
|
|
61
|
+
* chat context, letting the transport read the current chat id at send time
|
|
62
|
+
* without reaching into Elements internals.
|
|
63
|
+
*/
|
|
64
|
+
export type ElementsTransportFactory = (ctx: ElementsTransportContext) => ChatTransport<UIMessage>;
|
|
37
65
|
/**
|
|
38
66
|
* The top level configuration object for the Elements library.
|
|
39
67
|
*
|
|
@@ -49,6 +77,27 @@ export interface ElementsConfig {
|
|
|
49
77
|
* The system prompt to use for the Elements library.
|
|
50
78
|
*/
|
|
51
79
|
systemPrompt?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Optional chat transport override. When provided, Elements uses this
|
|
82
|
+
* transport instead of its built-in client-side streaming transport — e.g.
|
|
83
|
+
* to route the conversation through a persistent server-side assistant that
|
|
84
|
+
* generates replies and is polled for them. When omitted, the default
|
|
85
|
+
* client-side transport is used.
|
|
86
|
+
*
|
|
87
|
+
* May be a {@link ChatTransport} directly, or an {@link ElementsTransportFactory}
|
|
88
|
+
* that Elements invokes inside the provider with the live chat context — use
|
|
89
|
+
* the factory form when the transport needs the active chat id at send time.
|
|
90
|
+
*/
|
|
91
|
+
transport?: ChatTransport<UIMessage> | ElementsTransportFactory;
|
|
92
|
+
/**
|
|
93
|
+
* Whether to expose the inline message-edit affordance on user messages.
|
|
94
|
+
* Edit relies on assistant-ui's local branch rewriting; transports backed by a
|
|
95
|
+
* persistent server-side assistant typically can't honour that, so the
|
|
96
|
+
* sidebar uses this to hide the action rather than offer a broken control.
|
|
97
|
+
*
|
|
98
|
+
* @default true
|
|
99
|
+
*/
|
|
100
|
+
allowMessageEdit?: boolean;
|
|
52
101
|
/**
|
|
53
102
|
* Any plugins to use for the Elements library.
|
|
54
103
|
*
|
|
@@ -544,7 +593,7 @@ export interface ComponentOverrides {
|
|
|
544
593
|
export type ToolsFilter = string[] | (({ toolName }: {
|
|
545
594
|
toolName: string;
|
|
546
595
|
}) => boolean);
|
|
547
|
-
export type FrontendTools = Record<string,
|
|
596
|
+
export type FrontendTools = Record<string, AssistantTool>;
|
|
548
597
|
/**
|
|
549
598
|
* ToolsConfig is used to configure tool support in the Elements library.
|
|
550
599
|
* At the moment, you can override the default React components used by
|
|
@@ -710,6 +759,11 @@ export interface ContextCompactionConfig {
|
|
|
710
759
|
disabled?: boolean;
|
|
711
760
|
}
|
|
712
761
|
export interface WelcomeConfig {
|
|
762
|
+
/**
|
|
763
|
+
* Optional logo image URL shown above the title on the empty-thread welcome
|
|
764
|
+
* screen.
|
|
765
|
+
*/
|
|
766
|
+
logo?: string;
|
|
713
767
|
/**
|
|
714
768
|
* The welcome message to display when the thread is empty.
|
|
715
769
|
*/
|
|
@@ -898,6 +952,39 @@ export interface HistoryConfig {
|
|
|
898
952
|
* @default false
|
|
899
953
|
*/
|
|
900
954
|
enabled: boolean;
|
|
955
|
+
/**
|
|
956
|
+
* Extra query parameters forwarded to the thread-list request, used to
|
|
957
|
+
* filter which conversations are shown. Opaque to Elements — the consumer
|
|
958
|
+
* decides the keys (e.g. a search term, or a backend-specific scope). When
|
|
959
|
+
* omitted, all of the caller's chats are listed.
|
|
960
|
+
*/
|
|
961
|
+
threadListFilters?: Record<string, string>;
|
|
962
|
+
/**
|
|
963
|
+
* Let the backend own chat-id creation. When true, a brand-new thread does not
|
|
964
|
+
* get a client-generated id; instead the transport assigns the id (e.g. one
|
|
965
|
+
* the server minted on the first send, reported via the transport context's
|
|
966
|
+
* `adoptChatId`). Use with a server-backed `transport`.
|
|
967
|
+
*/
|
|
968
|
+
deferThreadIdMinting?: boolean;
|
|
969
|
+
/**
|
|
970
|
+
* Optional hook to transform or drop each persisted message before it is
|
|
971
|
+
* rendered from history. Return a (possibly rewritten) message to render it,
|
|
972
|
+
* or `null` to omit it entirely. Elements applies this to every message
|
|
973
|
+
* returned by `chat.load` before conversion.
|
|
974
|
+
*
|
|
975
|
+
* Use this to keep product- or backend-specific transcript conventions out of
|
|
976
|
+
* the library — e.g. stripping a server-injected framing block from a turn's
|
|
977
|
+
* text, or hiding system events that carry no user-facing content. Elements
|
|
978
|
+
* itself stays agnostic to any such convention.
|
|
979
|
+
*
|
|
980
|
+
* @example
|
|
981
|
+
* // Strip a server-injected framing block and hide framing-only turns.
|
|
982
|
+
* transformChatMessage: (msg) => {
|
|
983
|
+
* const cleaned = stripFraming(msg);
|
|
984
|
+
* return isFramingOnly(cleaned) ? null : cleaned;
|
|
985
|
+
* }
|
|
986
|
+
*/
|
|
987
|
+
transformChatMessage?: (message: GramChatMessage) => GramChatMessage | null;
|
|
901
988
|
/**
|
|
902
989
|
* Whether to show the thread list sidebar/panel.
|
|
903
990
|
* Only applicable for widget and sidecar variants.
|
|
@@ -937,5 +1024,7 @@ export type ElementsContextType = {
|
|
|
937
1024
|
setIsOpen: (isOpen: boolean) => void;
|
|
938
1025
|
plugins: Plugin[];
|
|
939
1026
|
mcpTools: Record<string, unknown> | undefined;
|
|
1027
|
+
/** True while the MCP tool list is actively being fetched. */
|
|
1028
|
+
mcpToolsLoading: boolean;
|
|
940
1029
|
};
|
|
941
1030
|
export {};
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@gram-ai/elements",
|
|
3
3
|
"description": "Gram Elements is a library of UI primitives for building chat-like experiences for MCP Servers.",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "1.
|
|
5
|
+
"version": "1.35.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
@@ -186,8 +186,6 @@
|
|
|
186
186
|
},
|
|
187
187
|
"devDependencies": {
|
|
188
188
|
"@ai-sdk/google": "^2",
|
|
189
|
-
"@eslint/compat": "^2.0.0",
|
|
190
|
-
"@eslint/js": "^9.39.1",
|
|
191
189
|
"@openrouter/sdk": "^0.3.14",
|
|
192
190
|
"@storybook/addon-docs": "^10.0.8",
|
|
193
191
|
"@storybook/react-vite": "^10.0.8",
|
|
@@ -198,10 +196,6 @@
|
|
|
198
196
|
"@types/node": "^24.10.1",
|
|
199
197
|
"@vitejs/plugin-react": "^5.0.3",
|
|
200
198
|
"chromatic": "^13.3.5",
|
|
201
|
-
"eslint": "^9.39.1",
|
|
202
|
-
"eslint-plugin-react-refresh": "^0.4.24",
|
|
203
|
-
"eslint-plugin-storybook": "^10.1.4",
|
|
204
|
-
"eslint-plugin-unused-imports": "^4.3.0",
|
|
205
199
|
"fastify": "^5.7.4",
|
|
206
200
|
"hono": "^4.11.7",
|
|
207
201
|
"lodash.merge": "^4.6.2",
|
|
@@ -216,7 +210,8 @@
|
|
|
216
210
|
"tw-animate-css": "^1.3.8",
|
|
217
211
|
"typedoc": "^0.28.15",
|
|
218
212
|
"typedoc-plugin-markdown": "^4.9.0",
|
|
219
|
-
"
|
|
213
|
+
"oxlint": "^1.67.0",
|
|
214
|
+
"oxlint-tsgolint": "^0.23.0",
|
|
220
215
|
"vite": "^7.1.6",
|
|
221
216
|
"vite-plugin-dts": "^4.5.4",
|
|
222
217
|
"vite-plugin-turbosnap": "^1.0.3",
|
|
@@ -232,7 +227,11 @@
|
|
|
232
227
|
"build": "vite build",
|
|
233
228
|
"test": "vitest run",
|
|
234
229
|
"test:watch": "vitest",
|
|
235
|
-
"lint": "
|
|
230
|
+
"lint": "pnpm lint:format && pnpm lint:no-barrels && pnpm lint:oxlint && pnpm type-check",
|
|
231
|
+
"lint:oxlint": "oxlint --type-aware",
|
|
232
|
+
"lint:fix": "oxlint --type-aware --fix",
|
|
233
|
+
"lint:format": "oxfmt --check .",
|
|
234
|
+
"lint:no-barrels": "! grep -rEn '^export \\*' src --include='*.ts' --include='*.tsx' || (echo 'Barrel re-exports (export *) are not allowed. Re-export named symbols instead.' && exit 1)",
|
|
236
235
|
"analyze": "pnpm dlx vite-bundle-visualizer",
|
|
237
236
|
"storybook": "pnpm clean:cache && storybook dev -p ${ELEMENTS_STORYBOOK_PORT:-6007} --no-open",
|
|
238
237
|
"build-storybook": "storybook build --stats-json",
|
package/src/compat-shims.ts
CHANGED
|
@@ -39,6 +39,7 @@ function createUseSyncExternalStoreShim(R: ReactLike) {
|
|
|
39
39
|
inst.value = value;
|
|
40
40
|
inst.getSnapshot = getSnapshot;
|
|
41
41
|
if (snapshotChanged(inst)) forceUpdate({ inst });
|
|
42
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
42
43
|
}, [subscribe, value, getSnapshot]);
|
|
43
44
|
|
|
44
45
|
R.useEffect(() => {
|
|
@@ -46,6 +47,7 @@ function createUseSyncExternalStoreShim(R: ReactLike) {
|
|
|
46
47
|
return subscribe(() => {
|
|
47
48
|
if (snapshotChanged(inst)) forceUpdate({ inst });
|
|
48
49
|
});
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
51
|
}, [subscribe]);
|
|
50
52
|
|
|
51
53
|
return value;
|
|
@@ -61,14 +63,26 @@ function createUseIdShim(R: ReactLike) {
|
|
|
61
63
|
};
|
|
62
64
|
}
|
|
63
65
|
|
|
66
|
+
export interface ReactShims {
|
|
67
|
+
useSyncExternalStore: <T>(
|
|
68
|
+
subscribe: (cb: () => void) => () => void,
|
|
69
|
+
getSnapshot: () => T,
|
|
70
|
+
) => T;
|
|
71
|
+
useId: () => string;
|
|
72
|
+
useInsertionEffect: typeof import("react").useLayoutEffect;
|
|
73
|
+
startTransition: (cb: () => void) => void;
|
|
74
|
+
useTransition: () => [boolean, (cb: () => void) => void];
|
|
75
|
+
useDeferredValue: <T>(value: T) => T;
|
|
76
|
+
}
|
|
77
|
+
|
|
64
78
|
/** Build polyfills for a React instance. Native APIs take precedence via ??. */
|
|
65
|
-
export function createShims(R: ReactLike) {
|
|
79
|
+
export function createShims(R: ReactLike): ReactShims {
|
|
66
80
|
return {
|
|
67
81
|
useSyncExternalStore:
|
|
68
82
|
R.useSyncExternalStore ?? createUseSyncExternalStoreShim(R),
|
|
69
83
|
useId: R.useId ?? createUseIdShim(R),
|
|
70
84
|
useInsertionEffect: R.useInsertionEffect ?? R.useLayoutEffect,
|
|
71
|
-
startTransition: R.startTransition ?? ((cb: () => void) => cb()),
|
|
85
|
+
startTransition: R.startTransition ?? ((cb: () => void): void => cb()),
|
|
72
86
|
useTransition:
|
|
73
87
|
R.useTransition ??
|
|
74
88
|
((): [boolean, (cb: () => void) => void] => [false, (cb) => cb()]),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
+
import * as React from "react";
|
|
3
4
|
import { useElements } from "@/hooks/useElements";
|
|
4
5
|
import { AssistantModal } from "../assistant-ui/assistant-modal";
|
|
5
6
|
import { AssistantSidecar } from "../assistant-ui/assistant-sidecar";
|
|
@@ -11,7 +12,7 @@ interface ChatProps {
|
|
|
11
12
|
className?: string;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
|
-
export const Chat = ({ className }: ChatProps) => {
|
|
15
|
+
export const Chat = ({ className }: ChatProps): React.JSX.Element => {
|
|
15
16
|
const { config } = useElements();
|
|
16
17
|
|
|
17
18
|
switch (config.variant) {
|
|
@@ -34,6 +35,8 @@ export const Chat = ({ className }: ChatProps) => {
|
|
|
34
35
|
|
|
35
36
|
// If no variant is provided then fallback to the modal
|
|
36
37
|
// Modal has its own internal ErrorBoundary around Thread
|
|
38
|
+
case "widget":
|
|
39
|
+
case undefined:
|
|
37
40
|
default:
|
|
38
41
|
return (
|
|
39
42
|
<ShadowRoot>
|
|
@@ -29,7 +29,7 @@ const FetchTool = defineFrontendTool<{ url: string }, string>(
|
|
|
29
29
|
const text = await response.text();
|
|
30
30
|
return text;
|
|
31
31
|
} catch (error) {
|
|
32
|
-
return `Error fetching ${url}: ${error instanceof Error ? error.message : "Unknown error"}. Note: URL must support CORS for browser requests.`;
|
|
32
|
+
return `Error fetching ${String(url)}: ${error instanceof Error ? error.message : "Unknown error"}. Note: URL must support CORS for browser requests.`;
|
|
33
33
|
}
|
|
34
34
|
},
|
|
35
35
|
},
|
|
@@ -93,8 +93,8 @@ const deleteFile = defineFrontendTool<{ fileId: string }, string>(
|
|
|
93
93
|
fileId: z.string().describe("The ID of the file to delete"),
|
|
94
94
|
}),
|
|
95
95
|
execute: async ({ fileId }) => {
|
|
96
|
-
alert(`File ${fileId} deleted`);
|
|
97
|
-
return `File ${fileId} deleted`;
|
|
96
|
+
alert(`File ${String(fileId)} deleted`);
|
|
97
|
+
return `File ${String(fileId)} deleted`;
|
|
98
98
|
},
|
|
99
99
|
},
|
|
100
100
|
"deleteFile",
|
|
@@ -139,7 +139,9 @@ const ProductCardComponent = ({ result }: ToolCallMessagePartProps) => {
|
|
|
139
139
|
${product.price?.toFixed(2)}
|
|
140
140
|
</span>
|
|
141
141
|
<button
|
|
142
|
-
onClick={
|
|
142
|
+
onClick={() => {
|
|
143
|
+
void handleAddToCart();
|
|
144
|
+
}}
|
|
143
145
|
disabled={
|
|
144
146
|
isLoading || addedToCart || !canAddToCart || !product.inStock
|
|
145
147
|
}
|
|
@@ -242,8 +244,10 @@ const ApproveRequestTool = defineFrontendTool<{ id: number }, string>(
|
|
|
242
244
|
}),
|
|
243
245
|
execute: async ({ id }) => {
|
|
244
246
|
// Simulate API call
|
|
245
|
-
await new Promise((resolve) =>
|
|
246
|
-
|
|
247
|
+
await new Promise((resolve) => {
|
|
248
|
+
setTimeout(resolve, 500);
|
|
249
|
+
});
|
|
250
|
+
return `Request #${String(id)} has been approved successfully.`;
|
|
247
251
|
},
|
|
248
252
|
},
|
|
249
253
|
"approve_request",
|
|
@@ -260,8 +264,12 @@ const RejectRequestTool = defineFrontendTool<
|
|
|
260
264
|
reason: z.string().optional().describe("Reason for rejection"),
|
|
261
265
|
}),
|
|
262
266
|
execute: async ({ id, reason }) => {
|
|
263
|
-
await new Promise((resolve) =>
|
|
264
|
-
|
|
267
|
+
await new Promise((resolve) => {
|
|
268
|
+
setTimeout(resolve, 500);
|
|
269
|
+
});
|
|
270
|
+
return `Request #${String(id)} has been rejected.${
|
|
271
|
+
reason ? ` Reason: ${JSON.stringify(reason)}` : ""
|
|
272
|
+
}`;
|
|
265
273
|
},
|
|
266
274
|
},
|
|
267
275
|
"reject_request",
|
|
@@ -7,7 +7,9 @@ interface ChatHistoryProps {
|
|
|
7
7
|
className?: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export const ChatHistory = ({
|
|
10
|
+
export const ChatHistory = ({
|
|
11
|
+
className,
|
|
12
|
+
}: ChatHistoryProps): React.JSX.Element => {
|
|
11
13
|
return (
|
|
12
14
|
<ShadowRoot hostStyle={{ height: "inherit", width: "inherit" }}>
|
|
13
15
|
<ThreadList className={className} />
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import type { StoryFn } from "@storybook/react-vite";
|
|
1
|
+
import type { Meta, StoryFn } from "@storybook/react-vite";
|
|
2
2
|
import { Chat } from "@/components/Chat";
|
|
3
3
|
import { Replay } from "@/components/Replay";
|
|
4
4
|
import type { Cassette } from "@/lib/cassette";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
const meta: any = {
|
|
6
|
+
const meta: Meta<typeof Replay> = {
|
|
8
7
|
title: "Misc/Replay",
|
|
9
8
|
component: Replay,
|
|
10
9
|
parameters: {
|
|
@@ -63,17 +63,20 @@ export const Replay = ({
|
|
|
63
63
|
userMessageDelay,
|
|
64
64
|
assistantStartDelay,
|
|
65
65
|
onComplete,
|
|
66
|
-
}: ReplayProps) => {
|
|
67
|
-
const replayOptions
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
}: ReplayProps): React.JSX.Element => {
|
|
67
|
+
const replayOptions = useMemo<ReplayOptions>(
|
|
68
|
+
() => ({
|
|
69
|
+
typingSpeed,
|
|
70
|
+
userMessageDelay,
|
|
71
|
+
assistantStartDelay,
|
|
72
|
+
onComplete,
|
|
73
|
+
}),
|
|
74
|
+
[typingSpeed, userMessageDelay, assistantStartDelay, onComplete],
|
|
75
|
+
);
|
|
73
76
|
|
|
74
77
|
const transport = useMemo(
|
|
75
78
|
() => createReplayTransport(cassette, replayOptions),
|
|
76
|
-
[cassette,
|
|
79
|
+
[cassette, replayOptions],
|
|
77
80
|
);
|
|
78
81
|
|
|
79
82
|
const runtime = useChatRuntime({ transport });
|
|
@@ -108,6 +111,7 @@ export const Replay = ({
|
|
|
108
111
|
setIsOpen: () => {},
|
|
109
112
|
plugins,
|
|
110
113
|
mcpTools: undefined,
|
|
114
|
+
mcpToolsLoading: false,
|
|
111
115
|
}),
|
|
112
116
|
[config, plugins],
|
|
113
117
|
);
|
|
@@ -148,7 +152,9 @@ export const Replay = ({
|
|
|
148
152
|
// ---------------------------------------------------------------------------
|
|
149
153
|
|
|
150
154
|
function sleep(ms: number): Promise<void> {
|
|
151
|
-
return new Promise((resolve) =>
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
setTimeout(resolve, ms);
|
|
157
|
+
});
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
/**
|
|
@@ -238,11 +244,12 @@ const ReplayController = ({ cassette, options }: ReplayControllerProps) => {
|
|
|
238
244
|
options.onComplete?.();
|
|
239
245
|
};
|
|
240
246
|
|
|
241
|
-
runReplay();
|
|
247
|
+
void runReplay();
|
|
242
248
|
|
|
243
249
|
return () => {
|
|
244
250
|
cancelled = true;
|
|
245
251
|
};
|
|
252
|
+
// oxlint-disable-next-line react-hooks/exhaustive-deps -- run-once driver, see hasStarted ref
|
|
246
253
|
}, []);
|
|
247
254
|
|
|
248
255
|
return null;
|
|
@@ -26,7 +26,7 @@ export const ShadowRoot = ({
|
|
|
26
26
|
children,
|
|
27
27
|
hostClassName,
|
|
28
28
|
hostStyle,
|
|
29
|
-
}: ShadowRootProps) => {
|
|
29
|
+
}: ShadowRootProps): React.JSX.Element => {
|
|
30
30
|
const hostRef = useRef<HTMLDivElement>(null);
|
|
31
31
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
32
32
|
const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);
|
|
@@ -66,7 +66,7 @@ export const ShadowRoot = ({
|
|
|
66
66
|
styleElement.setAttribute("data-gram-elements", "true");
|
|
67
67
|
styleElement.textContent = elementsStyles;
|
|
68
68
|
shadowRoot.prepend(styleElement);
|
|
69
|
-
}, [shadowRoot
|
|
69
|
+
}, [shadowRoot]);
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
72
|
<div
|
|
@@ -80,7 +80,7 @@ export function ShareButton({
|
|
|
80
80
|
size = "sm",
|
|
81
81
|
className,
|
|
82
82
|
children,
|
|
83
|
-
}: ShareButtonProps) {
|
|
83
|
+
}: ShareButtonProps): React.JSX.Element {
|
|
84
84
|
const { threadId } = useThreadId();
|
|
85
85
|
|
|
86
86
|
const handleShare = useCallback(async () => {
|
|
@@ -118,7 +118,9 @@ export function ShareButton({
|
|
|
118
118
|
<Button
|
|
119
119
|
variant={variant}
|
|
120
120
|
size={size}
|
|
121
|
-
onClick={
|
|
121
|
+
onClick={() => {
|
|
122
|
+
void handleShare();
|
|
123
|
+
}}
|
|
122
124
|
disabled={!threadId}
|
|
123
125
|
className={cn("aui-share-button", className)}
|
|
124
126
|
aria-label="Share chat"
|
|
@@ -36,9 +36,9 @@ const LAYOUT_TRANSITION = {
|
|
|
36
36
|
} as const;
|
|
37
37
|
|
|
38
38
|
type Dimensions = {
|
|
39
|
-
width?: string | number
|
|
40
|
-
height?: string | number
|
|
41
|
-
maxHeight?: string | number
|
|
39
|
+
width?: string | number;
|
|
40
|
+
height?: string | number;
|
|
41
|
+
maxHeight?: string | number;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
interface AssistantModalProps {
|
|
@@ -277,6 +277,8 @@ function positionClassname(
|
|
|
277
277
|
return "left-4 top-4";
|
|
278
278
|
case "bottom-right":
|
|
279
279
|
return "right-4 bottom-4";
|
|
280
|
+
case undefined:
|
|
281
|
+
return "right-4 bottom-4";
|
|
280
282
|
default:
|
|
281
283
|
assertNever(position);
|
|
282
284
|
}
|
|
@@ -140,7 +140,7 @@ const AttachmentUI: FC = () => {
|
|
|
140
140
|
return "File";
|
|
141
141
|
default: {
|
|
142
142
|
const _exhaustiveCheck: never = type;
|
|
143
|
-
throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
|
|
143
|
+
throw new Error(`Unknown attachment type: ${String(_exhaustiveCheck)}`);
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
});
|
|
@@ -90,7 +90,7 @@ export class ErrorBoundary extends Component<
|
|
|
90
90
|
this.props.onError?.(error, errorInfo);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
handleRetry = () => {
|
|
93
|
+
handleRetry = (): void => {
|
|
94
94
|
// Increment resetKey to force remount of children, reinitializing the chat
|
|
95
95
|
this.setState((state) => ({
|
|
96
96
|
hasError: false,
|
|
@@ -66,7 +66,7 @@ const useCopyToClipboard = ({
|
|
|
66
66
|
const copyToClipboard = (value: string) => {
|
|
67
67
|
if (!value) return;
|
|
68
68
|
|
|
69
|
-
navigator.clipboard.writeText(value).then(() => {
|
|
69
|
+
void navigator.clipboard.writeText(value).then(() => {
|
|
70
70
|
setIsCopied(true);
|
|
71
71
|
setTimeout(() => setIsCopied(false), copiedDuration);
|
|
72
72
|
});
|