@gram-ai/elements 1.27.4 → 1.27.5
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 +72 -60
- package/README.typedoc.md +6 -6
- package/bin/cli.js +74 -74
- package/dist/compat-shims-CO9JXXV4.cjs.map +1 -1
- package/dist/{compat-shims-BPJ7Q68c.js → compat-shims-DxtUrORi.js} +4 -2
- package/dist/compat-shims-DxtUrORi.js.map +1 -0
- package/dist/components/ShareButton/index.d.ts +2 -2
- package/dist/components/assistant-ui/message-feedback.d.ts +1 -1
- package/dist/components/assistant-ui/tooltip-icon-button.d.ts +2 -2
- package/dist/components/ui/avatar.d.ts +2 -2
- package/dist/components/ui/button.d.ts +1 -1
- package/dist/components/ui/calendar.d.ts +1 -1
- package/dist/components/ui/collapsible.d.ts +1 -1
- package/dist/components/ui/dialog.d.ts +4 -4
- package/dist/components/ui/popover.d.ts +2 -2
- package/dist/components/ui/skeleton.d.ts +1 -1
- package/dist/components/ui/time-range-picker.d.ts +1 -1
- package/dist/components/ui/tool-ui.d.ts +7 -7
- package/dist/components/ui/tooltip.d.ts +2 -2
- package/dist/contexts/ConnectionStatusContext.d.ts +1 -1
- package/dist/elements.cjs +1 -1
- package/dist/elements.js +2 -2
- package/dist/hooks/useDensity.d.ts +73 -73
- package/dist/hooks/useMCPTools.d.ts +1 -1
- package/dist/hooks/useRadius.d.ts +1 -1
- package/dist/{index-BpJstUh1.cjs → index-C4bFBGfl.cjs} +4 -4
- package/dist/{index-BpJstUh1.cjs.map → index-C4bFBGfl.cjs.map} +1 -1
- package/dist/{index-CUitXazZ.js → index-D93pV0_o.js} +55 -55
- package/dist/{index-CUitXazZ.js.map → index-D93pV0_o.js.map} +1 -1
- package/dist/{index-D0bAYNQy.js → index-DuCQRbcQ.js} +279 -265
- package/dist/index-DuCQRbcQ.js.map +1 -0
- package/dist/{index-KSX4Qjip.cjs → index-y_PNN5vK.cjs} +10 -10
- package/dist/index-y_PNN5vK.cjs.map +1 -0
- package/dist/lib/cassette.d.ts +4 -4
- package/dist/lib/errorTracking.d.ts +1 -1
- package/dist/lib/messageConverter.d.ts +1 -1
- package/dist/lib/models.d.ts +1 -1
- package/dist/plugins/chart/ui/bar-chart.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/accordion-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/accordion.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/action-button.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/alert-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/alert.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/avatar.d.ts +5 -5
- package/dist/plugins/generative-ui/ui/badge.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/button-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/button.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/card-wrapper.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/card.d.ts +8 -8
- package/dist/plugins/generative-ui/ui/checkbox.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/data-table.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/dialog.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/dropdown-menu.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/grid.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/input-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/input.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/label.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/metric.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/pagination.d.ts +6 -6
- package/dist/plugins/generative-ui/ui/popover.d.ts +4 -4
- package/dist/plugins/generative-ui/ui/progress.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/radio-group.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/select.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/separator.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/skeleton.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/stack.d.ts +6 -6
- package/dist/plugins/generative-ui/ui/switch.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/table.d.ts +9 -9
- package/dist/plugins/generative-ui/ui/tabs-wrapper.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/tabs.d.ts +1 -1
- package/dist/plugins/generative-ui/ui/text.d.ts +3 -3
- package/dist/plugins/generative-ui/ui/textarea.d.ts +2 -2
- package/dist/plugins/generative-ui/ui/tooltip.d.ts +1 -1
- package/dist/plugins.cjs +1 -1
- package/dist/plugins.js +1 -1
- package/dist/{profiler-BFkhZRxj.js → profiler-FpBY9eRv.js} +2 -2
- package/dist/{profiler-BFkhZRxj.js.map → profiler-FpBY9eRv.js.map} +1 -1
- package/dist/{profiler-CyzxBxVz.cjs → profiler-_mthyjvo.cjs} +2 -2
- package/dist/{profiler-CyzxBxVz.cjs.map → profiler-_mthyjvo.cjs.map} +1 -1
- package/dist/react-shim.js +1 -1
- package/dist/server/express.cjs.map +1 -1
- package/dist/server/express.js.map +1 -1
- package/dist/{startRecording-Dq92sEHf.cjs → startRecording-NJcpiHw-.cjs} +2 -2
- package/dist/{startRecording-Dq92sEHf.cjs.map → startRecording-NJcpiHw-.cjs.map} +1 -1
- package/dist/{startRecording-C-PPAs_Z.js → startRecording-r5MXQ2Dm.js} +2 -2
- package/dist/{startRecording-C-PPAs_Z.js.map → startRecording-r5MXQ2Dm.js.map} +1 -1
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -5
- package/src/compat-plugin.ts +14 -14
- package/src/compat-shims.ts +33 -31
- package/src/compat.test.ts +48 -48
- package/src/compat.ts +6 -6
- package/src/components/Chat/index.tsx +17 -17
- package/src/components/Chat/stories/Charts.stories.tsx +98 -98
- package/src/components/Chat/stories/Composer.stories.tsx +15 -15
- package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +44 -44
- package/src/components/Chat/stories/CustomComponents.stories.tsx +17 -17
- package/src/components/Chat/stories/Density.stories.tsx +20 -20
- package/src/components/Chat/stories/ErrorBoundary.stories.tsx +47 -47
- package/src/components/Chat/stories/FrontendTools.stories.tsx +39 -39
- package/src/components/Chat/stories/GenerativeUI.stories.tsx +48 -48
- package/src/components/Chat/stories/MessageFeedback.stories.tsx +52 -52
- package/src/components/Chat/stories/Modal.stories.tsx +28 -28
- package/src/components/Chat/stories/Model.stories.tsx +11 -11
- package/src/components/Chat/stories/Radius.stories.tsx +20 -20
- package/src/components/Chat/stories/Sidecar.stories.tsx +13 -13
- package/src/components/Chat/stories/StyleIsolation.stories.tsx +11 -11
- package/src/components/Chat/stories/Theme.stories.tsx +25 -25
- package/src/components/Chat/stories/Thread.stories.tsx +25 -25
- package/src/components/Chat/stories/ToolApproval.stories.tsx +55 -55
- package/src/components/Chat/stories/ToolMentions.stories.tsx +17 -17
- package/src/components/Chat/stories/Tools.stories.tsx +88 -88
- package/src/components/Chat/stories/Variants.stories.tsx +32 -32
- package/src/components/Chat/stories/Welcome.stories.tsx +14 -14
- package/src/components/ChatHistory.tsx +7 -7
- package/src/components/FrontendTools/index.tsx +5 -5
- package/src/components/Replay.stories.tsx +157 -157
- package/src/components/Replay.tsx +76 -73
- package/src/components/ShadowRoot.tsx +40 -40
- package/src/components/ShareButton/index.tsx +32 -32
- package/src/components/assistant-ui/assistant-modal.tsx +92 -87
- package/src/components/assistant-ui/assistant-sidecar.tsx +35 -35
- package/src/components/assistant-ui/attachment.tsx +80 -80
- package/src/components/assistant-ui/connection-status-indicator.tsx +33 -33
- package/src/components/assistant-ui/error-boundary.tsx +34 -34
- package/src/components/assistant-ui/follow-on-suggestions.tsx +26 -26
- package/src/components/assistant-ui/markdown-text.tsx +69 -69
- package/src/components/assistant-ui/mentioned-tools-badges.tsx +38 -38
- package/src/components/assistant-ui/message-feedback.tsx +57 -50
- package/src/components/assistant-ui/reasoning.tsx +83 -83
- package/src/components/assistant-ui/thread-list.tsx +45 -45
- package/src/components/assistant-ui/thread.tsx +278 -278
- package/src/components/assistant-ui/tool-fallback.tsx +37 -37
- package/src/components/assistant-ui/tool-group.tsx +26 -26
- package/src/components/assistant-ui/tool-mention-autocomplete.tsx +122 -122
- package/src/components/assistant-ui/tooltip-icon-button.tsx +18 -18
- package/src/components/ui/avatar.tsx +12 -12
- package/src/components/ui/button.tsx +12 -12
- package/src/components/ui/buttonVariants.ts +17 -17
- package/src/components/ui/calendar.tsx +106 -106
- package/src/components/ui/charts.stories.tsx +56 -56
- package/src/components/ui/collapsible.tsx +5 -5
- package/src/components/ui/dialog.tsx +30 -30
- package/src/components/ui/generative-ui.stories.tsx +200 -200
- package/src/components/ui/generative-ui.tsx +26 -26
- package/src/components/ui/popover.tsx +14 -14
- package/src/components/ui/skeleton.tsx +5 -5
- package/src/components/ui/time-range-picker.stories.tsx +80 -80
- package/src/components/ui/time-range-picker.tsx +245 -244
- package/src/components/ui/tool-ui.stories.tsx +37 -37
- package/src/components/ui/tool-ui.tsx +221 -215
- package/src/components/ui/tooltip.tsx +15 -15
- package/src/constants/tailwind.ts +1 -1
- package/src/contexts/ChatIdContext.tsx +7 -7
- package/src/contexts/ConnectionStatusContext.tsx +64 -64
- package/src/contexts/ElementsProvider.tsx +214 -213
- package/src/contexts/ReplayContext.ts +3 -3
- package/src/contexts/ToolApprovalContext.tsx +54 -54
- package/src/contexts/ToolExecutionContext.tsx +34 -34
- package/src/contexts/contexts.ts +7 -7
- package/src/contexts/portal-container-context.ts +2 -2
- package/src/contexts/portal-container.tsx +7 -7
- package/src/embedded.ts +1 -1
- package/src/global.css +25 -25
- package/src/hooks/useAuth.ts +72 -72
- package/src/hooks/useDensity.ts +79 -79
- package/src/hooks/useElements.ts +6 -6
- package/src/hooks/useExpanded.ts +12 -12
- package/src/hooks/useFollowOnSuggestions.ts +83 -83
- package/src/hooks/useGramThreadListAdapter.tsx +99 -99
- package/src/hooks/useMCPTools.ts +47 -47
- package/src/hooks/useModel.ts +14 -14
- package/src/hooks/usePluginComponents.ts +11 -11
- package/src/hooks/usePortalContainer.ts +5 -5
- package/src/hooks/useRadius.ts +23 -23
- package/src/hooks/useRecordCassette.ts +34 -34
- package/src/hooks/useSession.ts +11 -11
- package/src/hooks/useThemeProps.ts +13 -13
- package/src/hooks/useThreadId.ts +4 -4
- package/src/hooks/useToolApproval.ts +7 -7
- package/src/hooks/useToolMentions.ts +40 -40
- package/src/index.ts +26 -26
- package/src/lib/api.test.ts +61 -61
- package/src/lib/api.ts +4 -3
- package/src/lib/auth.ts +13 -13
- package/src/lib/cassette.ts +84 -84
- package/src/lib/easing.ts +1 -1
- package/src/lib/errorTracking.config.ts +5 -5
- package/src/lib/errorTracking.ts +29 -29
- package/src/lib/generative-ui.ts +7 -7
- package/src/lib/humanize.ts +3 -3
- package/src/lib/messageConverter.test.ts +130 -127
- package/src/lib/messageConverter.ts +196 -196
- package/src/lib/models.ts +21 -20
- package/src/lib/token.test.ts +56 -56
- package/src/lib/token.ts +14 -14
- package/src/lib/tool-mentions.ts +45 -45
- package/src/lib/tools.ts +66 -62
- package/src/lib/utils.ts +5 -5
- package/src/lib.d.ts +1 -1
- package/src/plugins/README.md +5 -5
- package/src/plugins/chart/catalog.ts +18 -18
- package/src/plugins/chart/chart.test.ts +31 -31
- package/src/plugins/chart/component.tsx +34 -34
- package/src/plugins/chart/index.ts +4 -4
- package/src/plugins/chart/ui/area-chart.tsx +42 -42
- package/src/plugins/chart/ui/bar-chart.tsx +46 -46
- package/src/plugins/chart/ui/donut-chart.tsx +48 -48
- package/src/plugins/chart/ui/index.ts +7 -7
- package/src/plugins/chart/ui/line-chart.tsx +43 -43
- package/src/plugins/chart/ui/pie-chart.tsx +44 -44
- package/src/plugins/chart/ui/radar-chart.tsx +33 -33
- package/src/plugins/chart/ui/scatter-chart.tsx +43 -43
- package/src/plugins/components/MacOSWindowFrame.tsx +15 -15
- package/src/plugins/components/PluginLoadingState.tsx +10 -10
- package/src/plugins/components/index.ts +1 -1
- package/src/plugins/generative-ui/catalog.ts +54 -54
- package/src/plugins/generative-ui/component.tsx +85 -85
- package/src/plugins/generative-ui/index.ts +4 -4
- package/src/plugins/generative-ui/ui/accordion-wrapper.tsx +16 -16
- package/src/plugins/generative-ui/ui/accordion.tsx +16 -16
- package/src/plugins/generative-ui/ui/action-button.tsx +28 -28
- package/src/plugins/generative-ui/ui/alert-wrapper.tsx +8 -8
- package/src/plugins/generative-ui/ui/alert.tsx +20 -20
- package/src/plugins/generative-ui/ui/avatar-wrapper.tsx +7 -7
- package/src/plugins/generative-ui/ui/avatar.tsx +30 -30
- package/src/plugins/generative-ui/ui/badge.tsx +22 -22
- package/src/plugins/generative-ui/ui/button-wrapper.tsx +12 -12
- package/src/plugins/generative-ui/ui/button.tsx +28 -28
- package/src/plugins/generative-ui/ui/card-wrapper.tsx +8 -8
- package/src/plugins/generative-ui/ui/card.tsx +27 -27
- package/src/plugins/generative-ui/ui/checkbox-wrapper.tsx +9 -9
- package/src/plugins/generative-ui/ui/checkbox.tsx +9 -9
- package/src/plugins/generative-ui/ui/data-table.tsx +8 -8
- package/src/plugins/generative-ui/ui/dialog.tsx +31 -31
- package/src/plugins/generative-ui/ui/dropdown-menu.tsx +44 -44
- package/src/plugins/generative-ui/ui/grid.tsx +12 -12
- package/src/plugins/generative-ui/ui/index.ts +40 -40
- package/src/plugins/generative-ui/ui/input-wrapper.tsx +11 -11
- package/src/plugins/generative-ui/ui/input.tsx +9 -9
- package/src/plugins/generative-ui/ui/label.tsx +8 -8
- package/src/plugins/generative-ui/ui/list.tsx +11 -11
- package/src/plugins/generative-ui/ui/metric.tsx +23 -23
- package/src/plugins/generative-ui/ui/pagination.tsx +28 -28
- package/src/plugins/generative-ui/ui/popover.tsx +21 -21
- package/src/plugins/generative-ui/ui/progress.tsx +13 -13
- package/src/plugins/generative-ui/ui/radio-group.tsx +12 -12
- package/src/plugins/generative-ui/ui/select-wrapper.tsx +7 -7
- package/src/plugins/generative-ui/ui/select.tsx +37 -37
- package/src/plugins/generative-ui/ui/separator.tsx +9 -9
- package/src/plugins/generative-ui/ui/skeleton-wrapper.tsx +10 -10
- package/src/plugins/generative-ui/ui/skeleton.tsx +5 -5
- package/src/plugins/generative-ui/ui/stack.tsx +28 -28
- package/src/plugins/generative-ui/ui/switch.tsx +11 -11
- package/src/plugins/generative-ui/ui/table.tsx +32 -32
- package/src/plugins/generative-ui/ui/tabs-wrapper.tsx +11 -11
- package/src/plugins/generative-ui/ui/tabs.tsx +26 -26
- package/src/plugins/generative-ui/ui/text.tsx +12 -12
- package/src/plugins/generative-ui/ui/textarea.tsx +7 -7
- package/src/plugins/generative-ui/ui/tooltip.tsx +12 -12
- package/src/plugins/index.ts +7 -7
- package/src/react-shim.ts +6 -6
- package/src/server/bun.ts +12 -12
- package/src/server/core.ts +25 -25
- package/src/server/express.ts +17 -15
- package/src/server/fastify.ts +14 -14
- package/src/server/hono.ts +9 -9
- package/src/server/nextjs.ts +12 -12
- package/src/server/tanstack-start.ts +12 -12
- package/src/server.ts +27 -27
- package/src/storybook.d.ts +4 -4
- package/src/types/index.ts +122 -122
- package/src/types/plugins.ts +7 -7
- package/src/vite-env.d.ts +12 -12
- package/dist/compat-shims-BPJ7Q68c.js.map +0 -1
- package/dist/index-D0bAYNQy.js.map +0 -1
- package/dist/index-KSX4Qjip.cjs.map +0 -1
package/src/lib/errorTracking.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { datadogRum } from
|
|
2
|
-
import { DATADOG_CONFIG } from
|
|
1
|
+
import { datadogRum } from "@datadog/browser-rum";
|
|
2
|
+
import { DATADOG_CONFIG } from "./errorTracking.config";
|
|
3
3
|
|
|
4
|
-
let initialized = false
|
|
5
|
-
let enabled = true
|
|
4
|
+
let initialized = false;
|
|
5
|
+
let enabled = true;
|
|
6
6
|
|
|
7
7
|
export interface ErrorTrackingConfig {
|
|
8
|
-
enabled?: boolean
|
|
9
|
-
projectSlug?: string
|
|
10
|
-
variant?: string
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
projectSlug?: string;
|
|
10
|
+
variant?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export interface ErrorContext {
|
|
14
|
-
source:
|
|
15
|
-
componentStack?: string
|
|
16
|
-
[key: string]: unknown
|
|
14
|
+
source: "error-boundary" | "streaming" | "stream-creation" | "custom";
|
|
15
|
+
componentStack?: string;
|
|
16
|
+
[key: string]: unknown;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/**
|
|
@@ -23,19 +23,19 @@ export interface ErrorContext {
|
|
|
23
23
|
export function initErrorTracking(config: ErrorTrackingConfig = {}): void {
|
|
24
24
|
// Check if explicitly disabled
|
|
25
25
|
if (config.enabled === false) {
|
|
26
|
-
enabled = false
|
|
27
|
-
return
|
|
26
|
+
enabled = false;
|
|
27
|
+
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
// Prevent double initialization
|
|
31
31
|
if (initialized) {
|
|
32
|
-
return
|
|
32
|
+
return;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Skip if credentials not configured (e.g., local dev without env vars)
|
|
36
36
|
if (!DATADOG_CONFIG.applicationId || !DATADOG_CONFIG.clientToken) {
|
|
37
|
-
enabled = false
|
|
38
|
-
return
|
|
37
|
+
enabled = false;
|
|
38
|
+
return;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
try {
|
|
@@ -44,7 +44,7 @@ export function initErrorTracking(config: ErrorTrackingConfig = {}): void {
|
|
|
44
44
|
clientToken: DATADOG_CONFIG.clientToken,
|
|
45
45
|
site: DATADOG_CONFIG.site,
|
|
46
46
|
service: DATADOG_CONFIG.service,
|
|
47
|
-
env: process.env.NODE_ENV ||
|
|
47
|
+
env: process.env.NODE_ENV || "production",
|
|
48
48
|
sessionSampleRate: 100,
|
|
49
49
|
sessionReplaySampleRate: 100,
|
|
50
50
|
trackUserInteractions: true,
|
|
@@ -53,21 +53,21 @@ export function initErrorTracking(config: ErrorTrackingConfig = {}): void {
|
|
|
53
53
|
|
|
54
54
|
// Note: we need to mask everything, not just user input, as sensitive data may be echo-ed
|
|
55
55
|
// back in the LLM messages or the user messages in the chat window
|
|
56
|
-
defaultPrivacyLevel:
|
|
57
|
-
})
|
|
56
|
+
defaultPrivacyLevel: "mask",
|
|
57
|
+
});
|
|
58
58
|
|
|
59
59
|
// Set global context
|
|
60
60
|
if (config.projectSlug) {
|
|
61
|
-
datadogRum.setGlobalContextProperty(
|
|
61
|
+
datadogRum.setGlobalContextProperty("projectSlug", config.projectSlug);
|
|
62
62
|
}
|
|
63
63
|
if (config.variant) {
|
|
64
|
-
datadogRum.setGlobalContextProperty(
|
|
64
|
+
datadogRum.setGlobalContextProperty("variant", config.variant);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
initialized = true
|
|
67
|
+
initialized = true;
|
|
68
68
|
} catch (error) {
|
|
69
|
-
console.warn(
|
|
70
|
-
enabled = false
|
|
69
|
+
console.warn("[Elements] Failed to initialize Datadog RUM:", error);
|
|
70
|
+
enabled = false;
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -77,22 +77,22 @@ export function initErrorTracking(config: ErrorTrackingConfig = {}): void {
|
|
|
77
77
|
*/
|
|
78
78
|
export function trackError(
|
|
79
79
|
error: Error | unknown,
|
|
80
|
-
context: ErrorContext
|
|
80
|
+
context: ErrorContext,
|
|
81
81
|
): void {
|
|
82
82
|
if (!enabled || !initialized) {
|
|
83
|
-
return
|
|
83
|
+
return;
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
const errorObj = error instanceof Error ? error : new Error(String(error))
|
|
86
|
+
const errorObj = error instanceof Error ? error : new Error(String(error));
|
|
87
87
|
|
|
88
88
|
try {
|
|
89
89
|
datadogRum.addError(errorObj, {
|
|
90
90
|
...context,
|
|
91
91
|
timestamp: new Date().toISOString(),
|
|
92
|
-
})
|
|
92
|
+
});
|
|
93
93
|
} catch (e) {
|
|
94
94
|
// Silently fail - we don't want error tracking to cause more errors
|
|
95
|
-
console.warn(
|
|
95
|
+
console.warn("[Elements] Failed to track error:", e);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -100,5 +100,5 @@ export function trackError(
|
|
|
100
100
|
* Check if error tracking is currently enabled.
|
|
101
101
|
*/
|
|
102
102
|
export function isErrorTrackingEnabled(): boolean {
|
|
103
|
-
return enabled && initialized
|
|
103
|
+
return enabled && initialized;
|
|
104
104
|
}
|
package/src/lib/generative-ui.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// Type for json-render tree structure
|
|
2
2
|
export interface JsonRenderNode {
|
|
3
|
-
type: string
|
|
4
|
-
props?: Record<string, unknown
|
|
5
|
-
children?: JsonRenderNode[]
|
|
3
|
+
type: string;
|
|
4
|
+
props?: Record<string, unknown>;
|
|
5
|
+
children?: JsonRenderNode[];
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -10,9 +10,9 @@ export interface JsonRenderNode {
|
|
|
10
10
|
*/
|
|
11
11
|
export function isJsonRenderTree(content: unknown): content is JsonRenderNode {
|
|
12
12
|
return (
|
|
13
|
-
typeof content ===
|
|
13
|
+
typeof content === "object" &&
|
|
14
14
|
content !== null &&
|
|
15
|
-
|
|
16
|
-
typeof (content as JsonRenderNode).type ===
|
|
17
|
-
)
|
|
15
|
+
"type" in content &&
|
|
16
|
+
typeof (content as JsonRenderNode).type === "string"
|
|
17
|
+
);
|
|
18
18
|
}
|
package/src/lib/humanize.ts
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
// - title case the string
|
|
6
6
|
export function humanizeToolName(toolName: string): string {
|
|
7
7
|
return toolName
|
|
8
|
-
.replace(/[-_]/g,
|
|
8
|
+
.replace(/[-_]/g, " ") // Replace hyphens and underscores with spaces
|
|
9
9
|
.split(/(?=[A-Z])/) // Split on camelCase boundaries
|
|
10
|
-
.join(
|
|
10
|
+
.join(" ") // Join with spaces
|
|
11
11
|
.split(/\s+/) // Split on any whitespace to normalize
|
|
12
12
|
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Title case each word
|
|
13
|
-
.join(
|
|
13
|
+
.join(" ");
|
|
14
14
|
}
|
|
@@ -1,82 +1,85 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { describe, expect, it } from
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
3
|
import {
|
|
4
4
|
convertGramMessagesToExported,
|
|
5
5
|
convertGramMessagesToUIMessages,
|
|
6
6
|
convertGramMessagePartsToUIMessageParts,
|
|
7
7
|
type GramChatMessage,
|
|
8
|
-
} from
|
|
8
|
+
} from "./messageConverter";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Helper to create a minimal GramChatMessage for testing.
|
|
12
12
|
*/
|
|
13
13
|
function makeMsg(
|
|
14
|
-
overrides: Partial<GramChatMessage> & { role: string }
|
|
14
|
+
overrides: Partial<GramChatMessage> & { role: string },
|
|
15
15
|
): GramChatMessage {
|
|
16
16
|
return {
|
|
17
17
|
id: crypto.randomUUID(),
|
|
18
|
-
model:
|
|
18
|
+
model: "test-model",
|
|
19
19
|
created_at: new Date().toISOString(),
|
|
20
20
|
...overrides,
|
|
21
|
-
} as GramChatMessage
|
|
21
|
+
} as GramChatMessage;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function makeToolCallsJSON(
|
|
25
|
-
calls: { id: string; name: string; args?: string }[]
|
|
25
|
+
calls: { id: string; name: string; args?: string }[],
|
|
26
26
|
): string {
|
|
27
27
|
return JSON.stringify(
|
|
28
28
|
calls.map((c) => ({
|
|
29
29
|
id: c.id,
|
|
30
|
-
type:
|
|
31
|
-
function: { name: c.name, arguments: c.args ??
|
|
32
|
-
}))
|
|
33
|
-
)
|
|
30
|
+
type: "function",
|
|
31
|
+
function: { name: c.name, arguments: c.args ?? "{}" },
|
|
32
|
+
})),
|
|
33
|
+
);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
describe(
|
|
37
|
-
it(
|
|
36
|
+
describe("convertGramMessagePartsToUIMessageParts", () => {
|
|
37
|
+
it("includes tool calls for a single assistant message", () => {
|
|
38
38
|
const msg = makeMsg({
|
|
39
|
-
role:
|
|
40
|
-
content:
|
|
41
|
-
tool_calls: makeToolCallsJSON([{ id:
|
|
42
|
-
} as Partial<GramChatMessage> & { role: string })
|
|
39
|
+
role: "assistant",
|
|
40
|
+
content: "Let me search.",
|
|
41
|
+
tool_calls: makeToolCallsJSON([{ id: "tc_1", name: "search_deals" }]),
|
|
42
|
+
} as Partial<GramChatMessage> & { role: string });
|
|
43
43
|
|
|
44
|
-
const parts = convertGramMessagePartsToUIMessageParts(
|
|
44
|
+
const parts = convertGramMessagePartsToUIMessageParts(
|
|
45
|
+
msg as any,
|
|
46
|
+
new Map(),
|
|
47
|
+
);
|
|
45
48
|
|
|
46
|
-
const toolParts = parts.filter((p) => p.type ===
|
|
47
|
-
expect(toolParts).toHaveLength(1)
|
|
49
|
+
const toolParts = parts.filter((p) => p.type === "dynamic-tool");
|
|
50
|
+
expect(toolParts).toHaveLength(1);
|
|
48
51
|
expect(toolParts[0]).toMatchObject({
|
|
49
|
-
type:
|
|
50
|
-
toolCallId:
|
|
51
|
-
toolName:
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
it(
|
|
56
|
-
const seen = new Set([
|
|
52
|
+
type: "dynamic-tool",
|
|
53
|
+
toolCallId: "tc_1",
|
|
54
|
+
toolName: "search_deals",
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("deduplicates tool calls when seenToolCallIds is provided", () => {
|
|
59
|
+
const seen = new Set(["tc_1"]);
|
|
57
60
|
const msg = makeMsg({
|
|
58
|
-
role:
|
|
59
|
-
content:
|
|
61
|
+
role: "assistant",
|
|
62
|
+
content: "Trying again.",
|
|
60
63
|
tool_calls: makeToolCallsJSON([
|
|
61
|
-
{ id:
|
|
62
|
-
{ id:
|
|
64
|
+
{ id: "tc_1", name: "search_deals" },
|
|
65
|
+
{ id: "tc_2", name: "search_deals" },
|
|
63
66
|
]),
|
|
64
|
-
} as Partial<GramChatMessage> & { role: string })
|
|
67
|
+
} as Partial<GramChatMessage> & { role: string });
|
|
65
68
|
|
|
66
69
|
const parts = convertGramMessagePartsToUIMessageParts(
|
|
67
70
|
msg as any,
|
|
68
71
|
new Map(),
|
|
69
|
-
seen
|
|
70
|
-
)
|
|
72
|
+
seen,
|
|
73
|
+
);
|
|
71
74
|
|
|
72
|
-
const toolParts = parts.filter((p) => p.type ===
|
|
73
|
-
expect(toolParts).toHaveLength(1)
|
|
74
|
-
expect(toolParts[0]).toMatchObject({ toolCallId:
|
|
75
|
-
expect(seen.has(
|
|
76
|
-
})
|
|
77
|
-
})
|
|
75
|
+
const toolParts = parts.filter((p) => p.type === "dynamic-tool");
|
|
76
|
+
expect(toolParts).toHaveLength(1);
|
|
77
|
+
expect(toolParts[0]).toMatchObject({ toolCallId: "tc_2" });
|
|
78
|
+
expect(seen.has("tc_2")).toBe(true);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
78
81
|
|
|
79
|
-
describe(
|
|
82
|
+
describe("convertGramMessagesToUIMessages - tool call deduplication", () => {
|
|
80
83
|
/**
|
|
81
84
|
* Simulates the server behavior where each assistant message in a multi-step
|
|
82
85
|
* tool use flow accumulates ALL tool calls from the turn, not just its own.
|
|
@@ -90,153 +93,153 @@ describe('convertGramMessagesToUIMessages - tool call deduplication', () => {
|
|
|
90
93
|
* Without dedup, each message renders all its tool calls → every group shows
|
|
91
94
|
* the accumulated count. With dedup, each message only renders the new ones.
|
|
92
95
|
*/
|
|
93
|
-
it(
|
|
96
|
+
it("deduplicates accumulated tool calls across assistant messages", () => {
|
|
94
97
|
const messages: GramChatMessage[] = [
|
|
95
98
|
makeMsg({
|
|
96
|
-
role:
|
|
97
|
-
content:
|
|
99
|
+
role: "user",
|
|
100
|
+
content: "Search for deals",
|
|
98
101
|
}),
|
|
99
102
|
makeMsg({
|
|
100
|
-
role:
|
|
103
|
+
role: "assistant",
|
|
101
104
|
content: "I'll search for deals.",
|
|
102
105
|
tool_calls: makeToolCallsJSON([
|
|
103
|
-
{ id:
|
|
106
|
+
{ id: "tc_1", name: "hubspot_search_deals" },
|
|
104
107
|
]),
|
|
105
108
|
} as Partial<GramChatMessage> & { role: string }),
|
|
106
109
|
makeMsg({
|
|
107
|
-
role:
|
|
110
|
+
role: "tool",
|
|
108
111
|
content: '{"error": "invalid filter"}',
|
|
109
|
-
tool_call_id:
|
|
112
|
+
tool_call_id: "tc_1",
|
|
110
113
|
} as Partial<GramChatMessage> & { role: string }),
|
|
111
114
|
makeMsg({
|
|
112
|
-
role:
|
|
113
|
-
content:
|
|
115
|
+
role: "assistant",
|
|
116
|
+
content: "Let me try differently.",
|
|
114
117
|
tool_calls: makeToolCallsJSON([
|
|
115
|
-
{ id:
|
|
116
|
-
{ id:
|
|
118
|
+
{ id: "tc_1", name: "hubspot_search_deals" },
|
|
119
|
+
{ id: "tc_2", name: "hubspot_search_deals" },
|
|
117
120
|
]),
|
|
118
121
|
} as Partial<GramChatMessage> & { role: string }),
|
|
119
122
|
makeMsg({
|
|
120
|
-
role:
|
|
123
|
+
role: "tool",
|
|
121
124
|
content: '{"error": "empty filters"}',
|
|
122
|
-
tool_call_id:
|
|
125
|
+
tool_call_id: "tc_2",
|
|
123
126
|
} as Partial<GramChatMessage> & { role: string }),
|
|
124
127
|
makeMsg({
|
|
125
|
-
role:
|
|
126
|
-
content:
|
|
128
|
+
role: "assistant",
|
|
129
|
+
content: "Let me try with proper filters.",
|
|
127
130
|
tool_calls: makeToolCallsJSON([
|
|
128
|
-
{ id:
|
|
129
|
-
{ id:
|
|
130
|
-
{ id:
|
|
131
|
+
{ id: "tc_1", name: "hubspot_search_deals" },
|
|
132
|
+
{ id: "tc_2", name: "hubspot_search_deals" },
|
|
133
|
+
{ id: "tc_3", name: "hubspot_search_deals" },
|
|
131
134
|
]),
|
|
132
135
|
} as Partial<GramChatMessage> & { role: string }),
|
|
133
136
|
makeMsg({
|
|
134
|
-
role:
|
|
137
|
+
role: "tool",
|
|
135
138
|
content: '{"deals": []}',
|
|
136
|
-
tool_call_id:
|
|
139
|
+
tool_call_id: "tc_3",
|
|
137
140
|
} as Partial<GramChatMessage> & { role: string }),
|
|
138
141
|
makeMsg({
|
|
139
|
-
role:
|
|
140
|
-
content:
|
|
142
|
+
role: "assistant",
|
|
143
|
+
content: "Here are the results.",
|
|
141
144
|
}),
|
|
142
|
-
]
|
|
145
|
+
];
|
|
143
146
|
|
|
144
|
-
const result = convertGramMessagesToUIMessages(messages)
|
|
147
|
+
const result = convertGramMessagesToUIMessages(messages);
|
|
145
148
|
const assistantMessages = result.messages.filter(
|
|
146
|
-
(m) => m.message.role ===
|
|
147
|
-
)
|
|
149
|
+
(m) => m.message.role === "assistant",
|
|
150
|
+
);
|
|
148
151
|
|
|
149
152
|
// Each assistant message should only have its OWN tool call, not all accumulated ones
|
|
150
153
|
const firstAssistant = assistantMessages[0]!.message.parts.filter(
|
|
151
|
-
(p) => p.type ===
|
|
152
|
-
)
|
|
153
|
-
expect(firstAssistant).toHaveLength(1)
|
|
154
|
-
expect(firstAssistant[0]).toMatchObject({ toolCallId:
|
|
154
|
+
(p) => p.type === "dynamic-tool",
|
|
155
|
+
);
|
|
156
|
+
expect(firstAssistant).toHaveLength(1);
|
|
157
|
+
expect(firstAssistant[0]).toMatchObject({ toolCallId: "tc_1" });
|
|
155
158
|
|
|
156
159
|
const secondAssistant = assistantMessages[1]!.message.parts.filter(
|
|
157
|
-
(p) => p.type ===
|
|
158
|
-
)
|
|
159
|
-
expect(secondAssistant).toHaveLength(1)
|
|
160
|
-
expect(secondAssistant[0]).toMatchObject({ toolCallId:
|
|
160
|
+
(p) => p.type === "dynamic-tool",
|
|
161
|
+
);
|
|
162
|
+
expect(secondAssistant).toHaveLength(1);
|
|
163
|
+
expect(secondAssistant[0]).toMatchObject({ toolCallId: "tc_2" });
|
|
161
164
|
|
|
162
165
|
const thirdAssistant = assistantMessages[2]!.message.parts.filter(
|
|
163
|
-
(p) => p.type ===
|
|
164
|
-
)
|
|
165
|
-
expect(thirdAssistant).toHaveLength(1)
|
|
166
|
-
expect(thirdAssistant[0]).toMatchObject({ toolCallId:
|
|
166
|
+
(p) => p.type === "dynamic-tool",
|
|
167
|
+
);
|
|
168
|
+
expect(thirdAssistant).toHaveLength(1);
|
|
169
|
+
expect(thirdAssistant[0]).toMatchObject({ toolCallId: "tc_3" });
|
|
167
170
|
|
|
168
171
|
// Final assistant message has no tool calls
|
|
169
172
|
const fourthAssistant = assistantMessages[3]!.message.parts.filter(
|
|
170
|
-
(p) => p.type ===
|
|
171
|
-
)
|
|
172
|
-
expect(fourthAssistant).toHaveLength(0)
|
|
173
|
-
})
|
|
173
|
+
(p) => p.type === "dynamic-tool",
|
|
174
|
+
);
|
|
175
|
+
expect(fourthAssistant).toHaveLength(0);
|
|
176
|
+
});
|
|
174
177
|
|
|
175
|
-
it(
|
|
178
|
+
it("resets dedup tracking after a user message", () => {
|
|
176
179
|
const messages: GramChatMessage[] = [
|
|
177
|
-
makeMsg({ role:
|
|
180
|
+
makeMsg({ role: "user", content: "First question" }),
|
|
178
181
|
makeMsg({
|
|
179
|
-
role:
|
|
180
|
-
content:
|
|
181
|
-
tool_calls: makeToolCallsJSON([{ id:
|
|
182
|
+
role: "assistant",
|
|
183
|
+
content: "Searching.",
|
|
184
|
+
tool_calls: makeToolCallsJSON([{ id: "tc_1", name: "search" }]),
|
|
182
185
|
} as Partial<GramChatMessage> & { role: string }),
|
|
183
186
|
makeMsg({
|
|
184
|
-
role:
|
|
185
|
-
content:
|
|
186
|
-
tool_call_id:
|
|
187
|
+
role: "tool",
|
|
188
|
+
content: "{}",
|
|
189
|
+
tool_call_id: "tc_1",
|
|
187
190
|
} as Partial<GramChatMessage> & { role: string }),
|
|
188
|
-
makeMsg({ role:
|
|
191
|
+
makeMsg({ role: "user", content: "Second question" }),
|
|
189
192
|
// New turn — tc_1 reused as ID (different conversation turn)
|
|
190
193
|
makeMsg({
|
|
191
|
-
role:
|
|
192
|
-
content:
|
|
193
|
-
tool_calls: makeToolCallsJSON([{ id:
|
|
194
|
+
role: "assistant",
|
|
195
|
+
content: "Searching again.",
|
|
196
|
+
tool_calls: makeToolCallsJSON([{ id: "tc_1", name: "search" }]),
|
|
194
197
|
} as Partial<GramChatMessage> & { role: string }),
|
|
195
|
-
]
|
|
198
|
+
];
|
|
196
199
|
|
|
197
|
-
const result = convertGramMessagesToUIMessages(messages)
|
|
200
|
+
const result = convertGramMessagesToUIMessages(messages);
|
|
198
201
|
const assistantMessages = result.messages.filter(
|
|
199
|
-
(m) => m.message.role ===
|
|
200
|
-
)
|
|
202
|
+
(m) => m.message.role === "assistant",
|
|
203
|
+
);
|
|
201
204
|
|
|
202
205
|
// Both assistant messages should have tc_1 since the user message resets tracking
|
|
203
206
|
const first = assistantMessages[0]!.message.parts.filter(
|
|
204
|
-
(p) => p.type ===
|
|
205
|
-
)
|
|
206
|
-
expect(first).toHaveLength(1)
|
|
207
|
+
(p) => p.type === "dynamic-tool",
|
|
208
|
+
);
|
|
209
|
+
expect(first).toHaveLength(1);
|
|
207
210
|
|
|
208
211
|
const second = assistantMessages[1]!.message.parts.filter(
|
|
209
|
-
(p) => p.type ===
|
|
210
|
-
)
|
|
211
|
-
expect(second).toHaveLength(1)
|
|
212
|
-
})
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
describe(
|
|
216
|
-
it(
|
|
212
|
+
(p) => p.type === "dynamic-tool",
|
|
213
|
+
);
|
|
214
|
+
expect(second).toHaveLength(1);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe("convertGramMessagesToExported - string content with tool calls", () => {
|
|
219
|
+
it("includes tool calls when assistant message has string content", () => {
|
|
217
220
|
const messages: GramChatMessage[] = [
|
|
218
|
-
makeMsg({ role:
|
|
221
|
+
makeMsg({ role: "user", content: "Search for deals" }),
|
|
219
222
|
makeMsg({
|
|
220
|
-
role:
|
|
221
|
-
content:
|
|
223
|
+
role: "assistant",
|
|
224
|
+
content: "Let me search.",
|
|
222
225
|
tool_calls: makeToolCallsJSON([
|
|
223
|
-
{ id:
|
|
226
|
+
{ id: "tc_1", name: "hubspot_search_deals" },
|
|
224
227
|
]),
|
|
225
228
|
} as Partial<GramChatMessage> & { role: string }),
|
|
226
|
-
]
|
|
229
|
+
];
|
|
227
230
|
|
|
228
|
-
const result = convertGramMessagesToExported(messages)
|
|
231
|
+
const result = convertGramMessagesToExported(messages);
|
|
229
232
|
const assistantEntry = result.messages.find(
|
|
230
|
-
(m) => m.message.role ===
|
|
231
|
-
)
|
|
233
|
+
(m) => m.message.role === "assistant",
|
|
234
|
+
)!;
|
|
232
235
|
const toolCallParts = (assistantEntry.message as any).content.filter(
|
|
233
|
-
(p: any) => p.type ===
|
|
234
|
-
)
|
|
235
|
-
expect(toolCallParts).toHaveLength(1)
|
|
236
|
+
(p: any) => p.type === "tool-call",
|
|
237
|
+
);
|
|
238
|
+
expect(toolCallParts).toHaveLength(1);
|
|
236
239
|
expect(toolCallParts[0]).toMatchObject({
|
|
237
|
-
type:
|
|
238
|
-
toolCallId:
|
|
239
|
-
toolName:
|
|
240
|
-
})
|
|
241
|
-
})
|
|
242
|
-
})
|
|
240
|
+
type: "tool-call",
|
|
241
|
+
toolCallId: "tc_1",
|
|
242
|
+
toolName: "hubspot_search_deals",
|
|
243
|
+
});
|
|
244
|
+
});
|
|
245
|
+
});
|