@gram-ai/elements 1.27.3 → 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 +4 -2
- 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.css +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-DBrhzauj.js → index-DuCQRbcQ.js} +6386 -6337
- package/dist/index-DuCQRbcQ.js.map +1 -0
- package/dist/{index-DxfW52oA.cjs → index-y_PNN5vK.cjs} +64 -46
- 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-D6ndqfsd.js → profiler-FpBY9eRv.js} +2 -2
- package/dist/{profiler-D6ndqfsd.js.map → profiler-FpBY9eRv.js.map} +1 -1
- package/dist/{profiler-DhnzZ34c.cjs → profiler-_mthyjvo.cjs} +2 -2
- package/dist/{profiler-DhnzZ34c.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-BwXmdmy1.cjs → startRecording-NJcpiHw-.cjs} +2 -2
- package/dist/{startRecording-BwXmdmy1.cjs.map → startRecording-NJcpiHw-.cjs.map} +1 -1
- package/dist/{startRecording-B_9CRZ_P.js → startRecording-r5MXQ2Dm.js} +2 -2
- package/dist/{startRecording-B_9CRZ_P.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 +74 -61
- 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 +272 -235
- 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 +222 -211
- 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 +87 -82
- 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-DBrhzauj.js.map +0 -1
- package/dist/index-DxfW52oA.cjs.map +0 -1
|
@@ -18,206 +18,206 @@ import type {
|
|
|
18
18
|
ThreadUserMessagePart,
|
|
19
19
|
ThreadAssistantMessagePart,
|
|
20
20
|
TextMessagePart,
|
|
21
|
-
} from
|
|
21
|
+
} from "@assistant-ui/react";
|
|
22
22
|
import type {
|
|
23
23
|
Message,
|
|
24
24
|
UserMessage,
|
|
25
25
|
AssistantMessage,
|
|
26
26
|
ToolResponseMessage,
|
|
27
|
-
} from
|
|
28
|
-
import { UIMessage } from
|
|
27
|
+
} from "@openrouter/sdk/models";
|
|
28
|
+
import { UIMessage } from "ai";
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Represents a chat message from the Gram API.
|
|
32
32
|
* This mirrors the ChatMessage type from @gram/sdk without requiring the SDK dependency.
|
|
33
33
|
*/
|
|
34
34
|
export type GramChatMessage = Message & {
|
|
35
|
-
id: string
|
|
36
|
-
model: string
|
|
37
|
-
created_at: Date | string
|
|
38
|
-
}
|
|
35
|
+
id: string;
|
|
36
|
+
model: string;
|
|
37
|
+
created_at: Date | string;
|
|
38
|
+
};
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Represents a chat from the Gram API.
|
|
42
42
|
*/
|
|
43
43
|
export interface GramChat {
|
|
44
|
-
id: string
|
|
45
|
-
title: string
|
|
46
|
-
userId: string
|
|
47
|
-
numMessages: number
|
|
48
|
-
messages: GramChatMessage[]
|
|
49
|
-
createdAt: Date | string
|
|
50
|
-
updatedAt: Date | string
|
|
44
|
+
id: string;
|
|
45
|
+
title: string;
|
|
46
|
+
userId: string;
|
|
47
|
+
numMessages: number;
|
|
48
|
+
messages: GramChatMessage[];
|
|
49
|
+
createdAt: Date | string;
|
|
50
|
+
updatedAt: Date | string;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Represents a chat overview from the Gram API (without full messages).
|
|
55
55
|
*/
|
|
56
56
|
export interface GramChatOverview {
|
|
57
|
-
id: string
|
|
58
|
-
title: string
|
|
59
|
-
userId: string
|
|
60
|
-
numMessages: number
|
|
61
|
-
createdAt: Date | string
|
|
62
|
-
updatedAt: Date | string
|
|
57
|
+
id: string;
|
|
58
|
+
title: string;
|
|
59
|
+
userId: string;
|
|
60
|
+
numMessages: number;
|
|
61
|
+
createdAt: Date | string;
|
|
62
|
+
updatedAt: Date | string;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Parses a date that might be a string or Date object.
|
|
67
67
|
*/
|
|
68
68
|
function parseDate(date: Date | string): Date {
|
|
69
|
-
return typeof date ===
|
|
69
|
+
return typeof date === "string" ? new Date(date) : date;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
73
|
* Builds content parts for a user message.
|
|
74
74
|
*/
|
|
75
75
|
function buildUserContentParts(msg: GramChatMessage): ThreadUserMessagePart[] {
|
|
76
|
-
if (msg.role !==
|
|
77
|
-
return []
|
|
76
|
+
if (msg.role !== "user") {
|
|
77
|
+
return [];
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
if (typeof msg.content ===
|
|
80
|
+
if (typeof msg.content === "string" || !msg.content) {
|
|
81
81
|
return [
|
|
82
82
|
{
|
|
83
|
-
type:
|
|
84
|
-
text: msg.content ??
|
|
83
|
+
type: "text",
|
|
84
|
+
text: msg.content ?? "",
|
|
85
85
|
},
|
|
86
|
-
]
|
|
86
|
+
];
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
const parts: ThreadUserMessagePart[] = []
|
|
89
|
+
const parts: ThreadUserMessagePart[] = [];
|
|
90
90
|
|
|
91
91
|
for (const item of msg.content) {
|
|
92
92
|
switch (item.type) {
|
|
93
|
-
case
|
|
93
|
+
case "text":
|
|
94
94
|
parts.push({
|
|
95
|
-
type:
|
|
95
|
+
type: "text",
|
|
96
96
|
text: item.text,
|
|
97
|
-
})
|
|
98
|
-
break
|
|
99
|
-
case
|
|
97
|
+
});
|
|
98
|
+
break;
|
|
99
|
+
case "image_url":
|
|
100
100
|
parts.push({
|
|
101
|
-
type:
|
|
101
|
+
type: "image",
|
|
102
102
|
image: (item as any).image_url?.url as FIXME<
|
|
103
103
|
string,
|
|
104
|
-
|
|
104
|
+
"Fixed by switching to Gram TS SDK."
|
|
105
105
|
>,
|
|
106
|
-
})
|
|
107
|
-
break
|
|
108
|
-
case
|
|
106
|
+
});
|
|
107
|
+
break;
|
|
108
|
+
case "input_audio": {
|
|
109
109
|
const format = (item as any).input_audio?.format as FIXME<
|
|
110
110
|
string,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (format ===
|
|
111
|
+
"Fixed by switching to Gram TS SDK."
|
|
112
|
+
>;
|
|
113
|
+
if (format === "mp3" || format === "wav") {
|
|
114
114
|
parts.push({
|
|
115
|
-
type:
|
|
115
|
+
type: "audio",
|
|
116
116
|
audio: {
|
|
117
117
|
data: (item as any).input_audio.data as FIXME<
|
|
118
118
|
string,
|
|
119
|
-
|
|
119
|
+
"Fixed by switching to Gram TS SDK."
|
|
120
120
|
>,
|
|
121
121
|
format: format,
|
|
122
122
|
},
|
|
123
|
-
})
|
|
123
|
+
});
|
|
124
124
|
}
|
|
125
|
-
break
|
|
125
|
+
break;
|
|
126
126
|
}
|
|
127
127
|
default:
|
|
128
128
|
parts.push({
|
|
129
|
-
type:
|
|
130
|
-
text:
|
|
131
|
-
})
|
|
132
|
-
break
|
|
129
|
+
type: "text",
|
|
130
|
+
text: "",
|
|
131
|
+
});
|
|
132
|
+
break;
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
return parts
|
|
136
|
+
return parts;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
140
|
* Builds content parts for an assistant message, including tool calls.
|
|
141
141
|
*/
|
|
142
142
|
function buildAssistantContentParts(
|
|
143
|
-
msg: GramChatMessage
|
|
143
|
+
msg: GramChatMessage,
|
|
144
144
|
): ThreadAssistantMessagePart[] {
|
|
145
|
-
if (msg.role !==
|
|
146
|
-
return []
|
|
145
|
+
if (msg.role !== "assistant") {
|
|
146
|
+
return [];
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
-
const parts: ThreadAssistantMessagePart[] = []
|
|
149
|
+
const parts: ThreadAssistantMessagePart[] = [];
|
|
150
150
|
|
|
151
|
-
if (typeof msg.content ===
|
|
151
|
+
if (typeof msg.content === "string" || !msg.content) {
|
|
152
152
|
parts.push({
|
|
153
|
-
type:
|
|
154
|
-
text: msg.content ??
|
|
155
|
-
})
|
|
153
|
+
type: "text",
|
|
154
|
+
text: msg.content ?? "",
|
|
155
|
+
});
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
const toolCallsJSON = (msg as any).tool_calls as FIXME<
|
|
159
159
|
string | undefined,
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
"Fixed by switching to Gram TS SDK."
|
|
161
|
+
>;
|
|
162
162
|
|
|
163
|
-
let toolCalls = tryParseJSON(toolCallsJSON ||
|
|
163
|
+
let toolCalls = tryParseJSON(toolCallsJSON || "[]");
|
|
164
164
|
if (!Array.isArray(toolCalls)) {
|
|
165
|
-
console.warn(
|
|
166
|
-
toolCalls = []
|
|
165
|
+
console.warn("Invalid tool_calls format, expected an array.");
|
|
166
|
+
toolCalls = [];
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
for (const tc of toolCalls) {
|
|
170
|
-
const args = tc.function?.arguments ?? tc.args ?? {}
|
|
171
|
-
const argsText = typeof args ===
|
|
170
|
+
const args = tc.function?.arguments ?? tc.args ?? {};
|
|
171
|
+
const argsText = typeof args === "string" ? args : JSON.stringify(args);
|
|
172
172
|
parts.push({
|
|
173
|
-
type:
|
|
174
|
-
toolCallId: tc.id ?? tc.toolCallId ??
|
|
175
|
-
toolName: tc.function?.name ?? tc.toolName ??
|
|
176
|
-
args: typeof args ===
|
|
173
|
+
type: "tool-call",
|
|
174
|
+
toolCallId: tc.id ?? tc.toolCallId ?? "",
|
|
175
|
+
toolName: tc.function?.name ?? tc.toolName ?? "",
|
|
176
|
+
args: typeof args === "string" ? JSON.parse(args) : args,
|
|
177
177
|
argsText,
|
|
178
178
|
result: undefined,
|
|
179
|
-
} as ThreadAssistantMessagePart)
|
|
179
|
+
} as ThreadAssistantMessagePart);
|
|
180
180
|
}
|
|
181
181
|
|
|
182
182
|
// Return at least an empty text part if no content
|
|
183
183
|
if (parts.length === 0) {
|
|
184
184
|
parts.push({
|
|
185
|
-
type:
|
|
186
|
-
text:
|
|
187
|
-
} as TextMessagePart)
|
|
185
|
+
type: "text",
|
|
186
|
+
text: "",
|
|
187
|
+
} as TextMessagePart);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
-
return parts
|
|
190
|
+
return parts;
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
function buildSystemContentParts(msg: GramChatMessage): [TextMessagePart] {
|
|
194
|
-
if (msg.role !==
|
|
195
|
-
return [{ type:
|
|
194
|
+
if (msg.role !== "system") {
|
|
195
|
+
return [{ type: "text", text: "" }];
|
|
196
196
|
}
|
|
197
197
|
|
|
198
|
-
if (typeof msg.content ===
|
|
199
|
-
return [{ type:
|
|
198
|
+
if (typeof msg.content === "string" || !msg.content) {
|
|
199
|
+
return [{ type: "text", text: msg.content ?? "" }];
|
|
200
200
|
}
|
|
201
201
|
|
|
202
|
-
const text: string[] = []
|
|
202
|
+
const text: string[] = [];
|
|
203
203
|
|
|
204
204
|
for (const item of msg.content) {
|
|
205
|
-
if (item.type !==
|
|
206
|
-
continue
|
|
205
|
+
if (item.type !== "text") {
|
|
206
|
+
continue;
|
|
207
207
|
}
|
|
208
|
-
text.push(item.text)
|
|
208
|
+
text.push(item.text);
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
-
return [{ type:
|
|
211
|
+
return [{ type: "text", text: text.join("\n") }];
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
/**
|
|
215
215
|
* Converts a single Gram ChatMessage to a ThreadMessage.
|
|
216
216
|
*/
|
|
217
217
|
function convertGramMessageToThreadMessage(
|
|
218
|
-
msg: GramChatMessage
|
|
218
|
+
msg: GramChatMessage,
|
|
219
219
|
): ThreadMessage {
|
|
220
|
-
const createdAt = parseDate(msg.created_at)
|
|
220
|
+
const createdAt = parseDate(msg.created_at);
|
|
221
221
|
|
|
222
222
|
const baseMetadata = {
|
|
223
223
|
unstable_state: undefined,
|
|
@@ -226,36 +226,36 @@ function convertGramMessageToThreadMessage(
|
|
|
226
226
|
steps: undefined,
|
|
227
227
|
submittedFeedback: undefined,
|
|
228
228
|
custom: {},
|
|
229
|
-
}
|
|
229
|
+
};
|
|
230
230
|
|
|
231
|
-
if (msg.role ===
|
|
231
|
+
if (msg.role === "user") {
|
|
232
232
|
return {
|
|
233
233
|
id: msg.id,
|
|
234
|
-
role:
|
|
234
|
+
role: "user",
|
|
235
235
|
createdAt,
|
|
236
236
|
content: buildUserContentParts(msg),
|
|
237
237
|
attachments: [],
|
|
238
238
|
metadata: baseMetadata,
|
|
239
|
-
}
|
|
239
|
+
};
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
if (msg.role ===
|
|
242
|
+
if (msg.role === "system") {
|
|
243
243
|
return {
|
|
244
244
|
id: msg.id,
|
|
245
|
-
role:
|
|
245
|
+
role: "system",
|
|
246
246
|
createdAt,
|
|
247
247
|
content: buildSystemContentParts(msg),
|
|
248
248
|
metadata: baseMetadata,
|
|
249
|
-
}
|
|
249
|
+
};
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
// Assistant message
|
|
253
253
|
return {
|
|
254
254
|
id: msg.id,
|
|
255
|
-
role:
|
|
255
|
+
role: "assistant",
|
|
256
256
|
createdAt,
|
|
257
257
|
content: buildAssistantContentParts(msg),
|
|
258
|
-
status: { type:
|
|
258
|
+
status: { type: "complete", reason: "stop" },
|
|
259
259
|
metadata: {
|
|
260
260
|
unstable_state: null,
|
|
261
261
|
unstable_annotations: [],
|
|
@@ -264,7 +264,7 @@ function convertGramMessageToThreadMessage(
|
|
|
264
264
|
submittedFeedback: undefined,
|
|
265
265
|
custom: {},
|
|
266
266
|
},
|
|
267
|
-
}
|
|
267
|
+
};
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
/**
|
|
@@ -275,252 +275,252 @@ function convertGramMessageToThreadMessage(
|
|
|
275
275
|
* `fromThreadMessageLike` doesn't support them in the exported format.
|
|
276
276
|
*/
|
|
277
277
|
export function convertGramMessagesToExported(
|
|
278
|
-
messages: GramChatMessage[]
|
|
278
|
+
messages: GramChatMessage[],
|
|
279
279
|
): ExportedMessageRepository {
|
|
280
280
|
if (messages.length === 0) {
|
|
281
|
-
return { messages: [], headId: null }
|
|
281
|
+
return { messages: [], headId: null };
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
-
const exportedMessages: ExportedMessageRepository[
|
|
285
|
-
let prevId: string | null = null
|
|
284
|
+
const exportedMessages: ExportedMessageRepository["messages"] = [];
|
|
285
|
+
let prevId: string | null = null;
|
|
286
286
|
|
|
287
287
|
for (const msg of messages) {
|
|
288
288
|
// Skip system messages - they're not supported in the exported message format
|
|
289
|
-
if (msg.role ===
|
|
290
|
-
continue
|
|
289
|
+
if (msg.role === "system") {
|
|
290
|
+
continue;
|
|
291
291
|
}
|
|
292
292
|
|
|
293
|
-
const threadMessage = convertGramMessageToThreadMessage(msg)
|
|
293
|
+
const threadMessage = convertGramMessageToThreadMessage(msg);
|
|
294
294
|
exportedMessages.push({
|
|
295
295
|
message: threadMessage,
|
|
296
296
|
parentId: prevId,
|
|
297
297
|
runConfig: undefined,
|
|
298
|
-
})
|
|
299
|
-
prevId = msg.id
|
|
298
|
+
});
|
|
299
|
+
prevId = msg.id;
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
return {
|
|
303
303
|
messages: exportedMessages,
|
|
304
304
|
headId: prevId,
|
|
305
|
-
}
|
|
305
|
+
};
|
|
306
306
|
}
|
|
307
307
|
|
|
308
308
|
export function convertGramMessagesToUIMessages(messages: GramChatMessage[]): {
|
|
309
|
-
headId: string | null
|
|
310
|
-
messages: { parentId: string | null; message: UIMessage }[]
|
|
309
|
+
headId: string | null;
|
|
310
|
+
messages: { parentId: string | null; message: UIMessage }[];
|
|
311
311
|
} {
|
|
312
312
|
if (messages.length === 0) {
|
|
313
|
-
return { messages: [], headId: null }
|
|
313
|
+
return { messages: [], headId: null };
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
-
const toolCallResults = new Map<string, ToolResponseMessage>()
|
|
316
|
+
const toolCallResults = new Map<string, ToolResponseMessage>();
|
|
317
317
|
for (const msg of messages) {
|
|
318
|
-
if (msg.role !==
|
|
319
|
-
continue
|
|
318
|
+
if (msg.role !== "tool") {
|
|
319
|
+
continue;
|
|
320
320
|
}
|
|
321
|
-
const id = (msg as any).tool_call_id
|
|
322
|
-
if (typeof id !==
|
|
323
|
-
continue
|
|
321
|
+
const id = (msg as any).tool_call_id;
|
|
322
|
+
if (typeof id !== "string") {
|
|
323
|
+
continue;
|
|
324
324
|
}
|
|
325
325
|
|
|
326
|
-
toolCallResults.set(id, msg as ToolResponseMessage)
|
|
326
|
+
toolCallResults.set(id, msg as ToolResponseMessage);
|
|
327
327
|
}
|
|
328
328
|
|
|
329
|
-
const uiMessages: { parentId: string | null; message: UIMessage }[] = []
|
|
330
|
-
let prevId: string | null = null
|
|
329
|
+
const uiMessages: { parentId: string | null; message: UIMessage }[] = [];
|
|
330
|
+
let prevId: string | null = null;
|
|
331
331
|
|
|
332
332
|
// Track tool call IDs across messages to deduplicate. The server accumulates
|
|
333
333
|
// all tool calls from a turn into each message, so without this, every
|
|
334
334
|
// assistant message in a multi-step tool use flow would show the full count.
|
|
335
|
-
const seenToolCallIds = new Set<string>()
|
|
335
|
+
const seenToolCallIds = new Set<string>();
|
|
336
336
|
|
|
337
337
|
for (const msg of messages) {
|
|
338
338
|
switch (msg.role) {
|
|
339
|
-
case
|
|
340
|
-
case
|
|
341
|
-
continue
|
|
342
|
-
case
|
|
339
|
+
case "developer":
|
|
340
|
+
case "tool":
|
|
341
|
+
continue;
|
|
342
|
+
case "system": {
|
|
343
343
|
uiMessages.push({
|
|
344
344
|
parentId: prevId,
|
|
345
345
|
message: {
|
|
346
346
|
id: msg.id,
|
|
347
|
-
role:
|
|
347
|
+
role: "system",
|
|
348
348
|
parts: [
|
|
349
349
|
{
|
|
350
|
-
type:
|
|
350
|
+
type: "text",
|
|
351
351
|
text:
|
|
352
|
-
typeof msg.content ===
|
|
352
|
+
typeof msg.content === "string"
|
|
353
353
|
? msg.content
|
|
354
354
|
: Array.isArray(msg.content)
|
|
355
355
|
? msg.content
|
|
356
|
-
.filter((item) => item.type ===
|
|
356
|
+
.filter((item) => item.type === "text")
|
|
357
357
|
.map((item) => item.text)
|
|
358
|
-
.join(
|
|
359
|
-
:
|
|
358
|
+
.join("\n")
|
|
359
|
+
: "",
|
|
360
360
|
},
|
|
361
361
|
],
|
|
362
362
|
},
|
|
363
|
-
})
|
|
364
|
-
break
|
|
363
|
+
});
|
|
364
|
+
break;
|
|
365
365
|
}
|
|
366
|
-
case
|
|
367
|
-
seenToolCallIds.clear()
|
|
366
|
+
case "user": {
|
|
367
|
+
seenToolCallIds.clear();
|
|
368
368
|
uiMessages.push({
|
|
369
369
|
parentId: prevId,
|
|
370
370
|
message: {
|
|
371
371
|
id: msg.id,
|
|
372
|
-
role:
|
|
372
|
+
role: "user",
|
|
373
373
|
parts: convertGramMessagePartsToUIMessageParts(
|
|
374
374
|
msg,
|
|
375
|
-
toolCallResults
|
|
375
|
+
toolCallResults,
|
|
376
376
|
),
|
|
377
377
|
},
|
|
378
|
-
})
|
|
379
|
-
break
|
|
378
|
+
});
|
|
379
|
+
break;
|
|
380
380
|
}
|
|
381
|
-
case
|
|
381
|
+
case "assistant": {
|
|
382
382
|
const uiMessage = {
|
|
383
383
|
parentId: prevId,
|
|
384
384
|
message: {
|
|
385
385
|
id: msg.id,
|
|
386
|
-
role:
|
|
386
|
+
role: "assistant",
|
|
387
387
|
parts: convertGramMessagePartsToUIMessageParts(
|
|
388
388
|
msg,
|
|
389
389
|
toolCallResults,
|
|
390
|
-
seenToolCallIds
|
|
390
|
+
seenToolCallIds,
|
|
391
391
|
),
|
|
392
392
|
} satisfies UIMessage,
|
|
393
|
-
}
|
|
394
|
-
uiMessages.push(uiMessage)
|
|
393
|
+
};
|
|
394
|
+
uiMessages.push(uiMessage);
|
|
395
395
|
|
|
396
|
-
break
|
|
396
|
+
break;
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
prevId = msg.id
|
|
400
|
+
prevId = msg.id;
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
return {
|
|
404
404
|
messages: uiMessages,
|
|
405
405
|
headId: prevId,
|
|
406
|
-
}
|
|
406
|
+
};
|
|
407
407
|
}
|
|
408
408
|
|
|
409
409
|
export function convertGramMessagePartsToUIMessageParts(
|
|
410
410
|
msg: UserMessage | AssistantMessage,
|
|
411
411
|
toolResults: Map<string, ToolResponseMessage>,
|
|
412
|
-
seenToolCallIds?: Set<string
|
|
413
|
-
): UIMessage[
|
|
414
|
-
const uiparts: UIMessage[
|
|
412
|
+
seenToolCallIds?: Set<string>,
|
|
413
|
+
): UIMessage["parts"] {
|
|
414
|
+
const uiparts: UIMessage["parts"] = [];
|
|
415
415
|
|
|
416
|
-
if (typeof msg.content ===
|
|
416
|
+
if (typeof msg.content === "string" && msg.content) {
|
|
417
417
|
uiparts.push({
|
|
418
|
-
type:
|
|
418
|
+
type: "text",
|
|
419
419
|
text: msg.content,
|
|
420
|
-
})
|
|
420
|
+
});
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
const content = Array.isArray(msg.content) ? msg.content : []
|
|
423
|
+
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
424
424
|
for (const p of content) {
|
|
425
425
|
switch (p.type) {
|
|
426
|
-
case
|
|
426
|
+
case "text": {
|
|
427
427
|
uiparts.push({
|
|
428
|
-
type:
|
|
428
|
+
type: "text",
|
|
429
429
|
text: p.text,
|
|
430
|
-
})
|
|
431
|
-
break
|
|
430
|
+
});
|
|
431
|
+
break;
|
|
432
432
|
}
|
|
433
|
-
case
|
|
433
|
+
case "image_url": {
|
|
434
434
|
const url = (p as any).image_url?.url as FIXME<
|
|
435
435
|
string | undefined,
|
|
436
|
-
|
|
437
|
-
|
|
436
|
+
"Fixed by switching to Gram TS SDK."
|
|
437
|
+
>;
|
|
438
438
|
if (!url) {
|
|
439
|
-
break
|
|
439
|
+
break;
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
uiparts.push({
|
|
443
|
-
type:
|
|
443
|
+
type: "file",
|
|
444
444
|
url,
|
|
445
445
|
mediaType: mediaTypeFromURL(url),
|
|
446
|
-
})
|
|
447
|
-
break
|
|
446
|
+
});
|
|
447
|
+
break;
|
|
448
448
|
}
|
|
449
|
-
case
|
|
449
|
+
case "input_audio": {
|
|
450
450
|
const url = (p as any).input_audio?.data as FIXME<
|
|
451
451
|
string | undefined,
|
|
452
|
-
|
|
453
|
-
|
|
452
|
+
"Fixed by switching to Gram TS SDK."
|
|
453
|
+
>;
|
|
454
454
|
if (!url) {
|
|
455
|
-
break
|
|
455
|
+
break;
|
|
456
456
|
}
|
|
457
457
|
|
|
458
458
|
uiparts.push({
|
|
459
|
-
type:
|
|
459
|
+
type: "file",
|
|
460
460
|
url,
|
|
461
461
|
mediaType: mediaTypeFromURL(url),
|
|
462
|
-
})
|
|
463
|
-
break
|
|
462
|
+
});
|
|
463
|
+
break;
|
|
464
464
|
}
|
|
465
465
|
}
|
|
466
466
|
}
|
|
467
467
|
|
|
468
|
-
if (msg.role ===
|
|
468
|
+
if (msg.role === "assistant" && msg.reasoning) {
|
|
469
469
|
uiparts.push({
|
|
470
|
-
type:
|
|
470
|
+
type: "reasoning",
|
|
471
471
|
text: msg.reasoning,
|
|
472
|
-
})
|
|
472
|
+
});
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
if (msg.role ===
|
|
475
|
+
if (msg.role === "assistant" && (msg as any).tool_calls) {
|
|
476
476
|
const toolCallsJSON = (msg as any).tool_calls as FIXME<
|
|
477
477
|
string,
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
let toolCalls = tryParseJSON<AssistantMessage[
|
|
481
|
-
toolCallsJSON ||
|
|
482
|
-
)
|
|
478
|
+
"Fixed by switching to Gram TS SDK."
|
|
479
|
+
>;
|
|
480
|
+
let toolCalls = tryParseJSON<AssistantMessage["toolCalls"]>(
|
|
481
|
+
toolCallsJSON || "[]",
|
|
482
|
+
);
|
|
483
483
|
if (!Array.isArray(toolCalls)) {
|
|
484
|
-
console.warn(
|
|
485
|
-
toolCalls = []
|
|
484
|
+
console.warn("Invalid tool_calls format, expected an array.");
|
|
485
|
+
toolCalls = [];
|
|
486
486
|
}
|
|
487
487
|
|
|
488
488
|
for (const tc of toolCalls) {
|
|
489
489
|
// The server accumulates all tool calls from a turn into each message's
|
|
490
490
|
// tool_calls field. Deduplicate across messages so each tool call only
|
|
491
491
|
// appears in the first message that references it.
|
|
492
|
-
if (seenToolCallIds?.has(tc.id)) continue
|
|
493
|
-
seenToolCallIds?.add(tc.id)
|
|
492
|
+
if (seenToolCallIds?.has(tc.id)) continue;
|
|
493
|
+
seenToolCallIds?.add(tc.id);
|
|
494
494
|
|
|
495
|
-
const content = toolResults.get(tc.id)?.content
|
|
495
|
+
const content = toolResults.get(tc.id)?.content;
|
|
496
496
|
uiparts.push({
|
|
497
|
-
type:
|
|
497
|
+
type: "dynamic-tool",
|
|
498
498
|
toolCallId: tc.id,
|
|
499
|
-
toolName: tc.function?.name ??
|
|
500
|
-
state:
|
|
499
|
+
toolName: tc.function?.name ?? "",
|
|
500
|
+
state: "output-available",
|
|
501
501
|
input: tc.function?.arguments ?? {},
|
|
502
|
-
output: typeof content ===
|
|
503
|
-
})
|
|
502
|
+
output: typeof content === "string" ? tryParseJSON(content) : "",
|
|
503
|
+
});
|
|
504
504
|
}
|
|
505
505
|
}
|
|
506
506
|
|
|
507
|
-
return uiparts
|
|
507
|
+
return uiparts;
|
|
508
508
|
}
|
|
509
509
|
|
|
510
510
|
function mediaTypeFromURL(url: string): string {
|
|
511
|
-
const unspecified =
|
|
512
|
-
if (!url.startsWith(
|
|
513
|
-
return unspecified
|
|
511
|
+
const unspecified = "unknown/unknown";
|
|
512
|
+
if (!url.startsWith("data:")) {
|
|
513
|
+
return unspecified;
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
-
const match = url.match(/^data:([^;]+);/)
|
|
517
|
-
return match?.[1] || unspecified
|
|
516
|
+
const match = url.match(/^data:([^;]+);/);
|
|
517
|
+
return match?.[1] || unspecified;
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
function tryParseJSON<T = any>(str: string): T | null {
|
|
521
521
|
try {
|
|
522
|
-
return JSON.parse(str) as T
|
|
522
|
+
return JSON.parse(str) as T;
|
|
523
523
|
} catch {
|
|
524
|
-
return null
|
|
524
|
+
return null;
|
|
525
525
|
}
|
|
526
526
|
}
|