@gram-ai/elements 1.20.2 → 1.21.2
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/bin/cli.js +14 -12
- package/dist/components/Chat/stories/ConnectionConfiguration.stories.d.ts +2 -2
- package/dist/components/Chat/stories/ToolApproval.stories.d.ts +2 -0
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/tooltip.d.ts +3 -1
- package/dist/constants/tailwind.d.ts +1 -0
- package/dist/contexts/portal-container-context.d.ts +2 -0
- package/dist/contexts/portal-container.d.ts +7 -0
- package/dist/elements.cjs +1 -160
- package/dist/elements.cjs.map +1 -1
- package/dist/elements.css +1 -1
- package/dist/elements.js +11 -47215
- package/dist/elements.js.map +1 -1
- package/dist/hooks/usePortalContainer.d.ts +8 -0
- package/dist/hooks/useSession.d.ts +1 -2
- package/dist/index-BVvrv2G3.cjs +169 -0
- package/dist/index-BVvrv2G3.cjs.map +1 -0
- package/dist/index-OU3wjArm.js +54670 -0
- package/dist/index-OU3wjArm.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/lib/auth.d.ts +2 -2
- package/dist/lib/errorTracking.config.d.ts +16 -0
- package/dist/lib/errorTracking.d.ts +24 -0
- package/dist/lib/tools.d.ts +3 -2
- package/dist/profiler-DPH9zydw.cjs +2 -0
- package/dist/profiler-DPH9zydw.cjs.map +1 -0
- package/dist/profiler-D_HNXmyv.js +278 -0
- package/dist/profiler-D_HNXmyv.js.map +1 -0
- package/dist/startRecording-B97e4Mlu.cjs +3 -0
- package/dist/startRecording-B97e4Mlu.cjs.map +1 -0
- package/dist/startRecording-DOMzQAAr.js +1212 -0
- package/dist/startRecording-DOMzQAAr.js.map +1 -0
- package/dist/types/index.d.ts +45 -15
- package/package.json +16 -2
- package/src/components/Chat/index.tsx +31 -3
- package/src/components/Chat/stories/Composer.stories.tsx +0 -7
- package/src/components/Chat/stories/ConnectionConfiguration.stories.tsx +7 -14
- package/src/components/Chat/stories/CustomComponents.stories.tsx +0 -7
- package/src/components/Chat/stories/Density.stories.tsx +0 -7
- package/src/components/Chat/stories/ErrorBoundary.stories.tsx +4 -23
- package/src/components/Chat/stories/FrontendTools.stories.tsx +0 -7
- package/src/components/Chat/stories/Model.stories.tsx +0 -7
- package/src/components/Chat/stories/Plugins.stories.tsx +0 -7
- package/src/components/Chat/stories/Radius.stories.tsx +0 -7
- package/src/components/Chat/stories/ToolApproval.stories.tsx +51 -7
- package/src/components/Chat/stories/Tools.stories.tsx +0 -7
- package/src/components/Chat/stories/Variants.stories.tsx +5 -2
- package/src/components/Chat/stories/Welcome.stories.tsx +0 -8
- package/src/components/assistant-ui/assistant-sidecar.tsx +1 -4
- package/src/components/assistant-ui/attachment.tsx +1 -4
- package/src/components/assistant-ui/error-boundary.tsx +6 -0
- package/src/components/assistant-ui/thread-list.tsx +3 -1
- package/src/components/assistant-ui/thread.tsx +10 -12
- package/src/components/ui/dialog.tsx +10 -1
- package/src/components/ui/popover.tsx +10 -12
- package/src/components/ui/tooltip.tsx +7 -2
- package/src/constants/tailwind.ts +2 -0
- package/src/contexts/ElementsProvider.tsx +13 -1
- package/src/contexts/portal-container-context.ts +4 -0
- package/src/contexts/portal-container.tsx +20 -0
- package/src/global.css +129 -16
- package/src/hooks/useAuth.ts +6 -16
- package/src/hooks/usePortalContainer.ts +16 -0
- package/src/hooks/useSession.ts +1 -3
- package/src/index.ts +5 -0
- package/src/lib/api.test.ts +5 -5
- package/src/lib/auth.ts +4 -4
- package/src/lib/errorTracking.config.ts +16 -0
- package/src/lib/errorTracking.ts +104 -0
- package/src/lib/tools.ts +37 -8
- package/src/types/index.ts +48 -16
- package/src/vite-env.d.ts +3 -0
- package/dist/components/Chat/stories/ColorScheme.stories.d.ts +0 -8
- package/src/components/Chat/stories/ColorScheme.stories.tsx +0 -52
|
@@ -10,13 +10,6 @@ const meta: Meta<typeof Chat> = {
|
|
|
10
10
|
parameters: {
|
|
11
11
|
layout: 'fullscreen',
|
|
12
12
|
},
|
|
13
|
-
decorators: [
|
|
14
|
-
(Story) => (
|
|
15
|
-
<div className="m-auto flex h-screen w-full max-w-3xl flex-col">
|
|
16
|
-
<Story />
|
|
17
|
-
</div>
|
|
18
|
-
),
|
|
19
|
-
],
|
|
20
13
|
} satisfies Meta<typeof Chat>
|
|
21
14
|
|
|
22
15
|
export default meta
|
|
@@ -44,6 +37,30 @@ SingleTool.parameters = {
|
|
|
44
37
|
},
|
|
45
38
|
}
|
|
46
39
|
|
|
40
|
+
export const SingleToolWithFunction: Story = () => <Chat />
|
|
41
|
+
SingleToolWithFunction.storyName =
|
|
42
|
+
'Single Tool Requiring Approval with Function'
|
|
43
|
+
SingleToolWithFunction.parameters = {
|
|
44
|
+
elements: {
|
|
45
|
+
config: {
|
|
46
|
+
variant: 'standalone',
|
|
47
|
+
tools: {
|
|
48
|
+
toolsRequiringApproval: ({ toolName }: { toolName: string }) =>
|
|
49
|
+
toolName.endsWith('salutation'),
|
|
50
|
+
},
|
|
51
|
+
welcome: {
|
|
52
|
+
suggestions: [
|
|
53
|
+
{
|
|
54
|
+
title: 'Call a tool requiring approval',
|
|
55
|
+
label: 'Get a salutation',
|
|
56
|
+
action: 'Get a salutation',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
|
|
47
64
|
export const MultipleGroupedTools: Story = () => <Chat />
|
|
48
65
|
MultipleGroupedTools.storyName = 'Multiple Grouped Tools'
|
|
49
66
|
MultipleGroupedTools.parameters = {
|
|
@@ -108,3 +125,30 @@ FrontendTool.parameters = {
|
|
|
108
125
|
},
|
|
109
126
|
},
|
|
110
127
|
}
|
|
128
|
+
|
|
129
|
+
export const FrontendToolWithFunction: Story = () => <Chat />
|
|
130
|
+
FrontendToolWithFunction.storyName =
|
|
131
|
+
'Frontend Tool Requiring Approval with Function'
|
|
132
|
+
FrontendToolWithFunction.parameters = {
|
|
133
|
+
elements: {
|
|
134
|
+
config: {
|
|
135
|
+
variant: 'standalone',
|
|
136
|
+
tools: {
|
|
137
|
+
frontendTools: {
|
|
138
|
+
deleteFile,
|
|
139
|
+
},
|
|
140
|
+
toolsRequiringApproval: ({ toolName }: { toolName: string }) =>
|
|
141
|
+
toolName.startsWith('delete'),
|
|
142
|
+
},
|
|
143
|
+
welcome: {
|
|
144
|
+
suggestions: [
|
|
145
|
+
{
|
|
146
|
+
title: 'Delete a file',
|
|
147
|
+
label: 'Delete a file',
|
|
148
|
+
action: 'Delete file with ID 123',
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
},
|
|
154
|
+
}
|
|
@@ -9,13 +9,6 @@ const meta: Meta<typeof Chat> = {
|
|
|
9
9
|
parameters: {
|
|
10
10
|
layout: 'fullscreen',
|
|
11
11
|
},
|
|
12
|
-
decorators: [
|
|
13
|
-
(Story) => (
|
|
14
|
-
<div className="m-auto flex h-screen w-full max-w-3xl flex-col">
|
|
15
|
-
<Story />
|
|
16
|
-
</div>
|
|
17
|
-
),
|
|
18
|
-
],
|
|
19
12
|
} satisfies Meta<typeof Chat>
|
|
20
13
|
|
|
21
14
|
export default meta
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Chat } from '..'
|
|
2
2
|
import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite'
|
|
3
3
|
import { ThreadList } from '@/components/assistant-ui/thread-list'
|
|
4
|
+
import { ROOT_SELECTOR } from '@/constants/tailwind'
|
|
4
5
|
|
|
5
6
|
const meta: Meta<typeof Chat> = {
|
|
6
7
|
title: 'Chat/Variants',
|
|
@@ -46,8 +47,10 @@ export const StandaloneWithHistory: StoryObj<typeof Chat> = {
|
|
|
46
47
|
}
|
|
47
48
|
StandaloneWithHistory.decorators = [
|
|
48
49
|
(Story) => (
|
|
49
|
-
<div className=
|
|
50
|
-
<
|
|
50
|
+
<div className={ROOT_SELECTOR}>
|
|
51
|
+
<div className="m-auto flex h-screen w-full items-center justify-center border bg-linear-to-r from-violet-600 to-indigo-800">
|
|
52
|
+
<Story />
|
|
53
|
+
</div>
|
|
51
54
|
</div>
|
|
52
55
|
),
|
|
53
56
|
]
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
1
|
import { Chat } from '..'
|
|
3
2
|
import type { Meta, StoryFn } from '@storybook/react-vite'
|
|
4
3
|
|
|
@@ -8,13 +7,6 @@ const meta: Meta<typeof Chat> = {
|
|
|
8
7
|
parameters: {
|
|
9
8
|
layout: 'fullscreen',
|
|
10
9
|
},
|
|
11
|
-
decorators: [
|
|
12
|
-
(Story) => (
|
|
13
|
-
<div className="m-auto flex h-screen w-full max-w-3xl flex-col">
|
|
14
|
-
<Story />
|
|
15
|
-
</div>
|
|
16
|
-
),
|
|
17
|
-
],
|
|
18
10
|
} satisfies Meta<typeof Chat>
|
|
19
11
|
|
|
20
12
|
export default meta
|
|
@@ -37,10 +37,7 @@ export const AssistantSidecar: FC<AssistantSidecarProps> = ({ className }) => {
|
|
|
37
37
|
return (
|
|
38
38
|
<LazyMotion features={domMax}>
|
|
39
39
|
<m.div
|
|
40
|
-
initial={
|
|
41
|
-
width: dimensions?.default?.width ?? '400px',
|
|
42
|
-
height: dimensions?.default?.height ?? '100vh',
|
|
43
|
-
}}
|
|
40
|
+
initial={false}
|
|
44
41
|
animate={{
|
|
45
42
|
width: isExpanded
|
|
46
43
|
? (dimensions?.expanded?.width ?? '800px')
|
|
@@ -87,10 +87,7 @@ const AttachmentPreviewDialog: FC<PropsWithChildren> = ({ children }) => {
|
|
|
87
87
|
|
|
88
88
|
return (
|
|
89
89
|
<Dialog>
|
|
90
|
-
<DialogTrigger
|
|
91
|
-
className="aui-attachment-preview-trigger hover:bg-accent/50 cursor-pointer transition-colors"
|
|
92
|
-
asChild
|
|
93
|
-
>
|
|
90
|
+
<DialogTrigger className="aui-attachment-preview-trigger" asChild>
|
|
94
91
|
{children}
|
|
95
92
|
</DialogTrigger>
|
|
96
93
|
<DialogContent className="aui-attachment-preview-dialog-content [&_svg]:text-background [&>button]:bg-foreground/60 [&>button]:hover:[&_svg]:text-destructive p-2 sm:max-w-3xl [&>button]:rounded-full [&>button]:p-1 [&>button]:opacity-100 [&>button]:!ring-0">
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { AlertCircle } from 'lucide-react'
|
|
4
4
|
import { Component, type ErrorInfo, type ReactNode } from 'react'
|
|
5
|
+
import { trackError } from '@/lib/errorTracking'
|
|
5
6
|
import { cn } from '@/lib/utils'
|
|
6
7
|
import { Button } from '../ui/button'
|
|
7
8
|
|
|
@@ -81,6 +82,11 @@ export class ErrorBoundary extends Component<
|
|
|
81
82
|
}
|
|
82
83
|
|
|
83
84
|
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
|
|
85
|
+
// Track error to Datadog RUM
|
|
86
|
+
trackError(error, {
|
|
87
|
+
source: 'error-boundary',
|
|
88
|
+
componentStack: errorInfo.componentStack ?? undefined,
|
|
89
|
+
})
|
|
84
90
|
this.props.onError?.(error, errorInfo)
|
|
85
91
|
}
|
|
86
92
|
|
|
@@ -11,6 +11,7 @@ import { Skeleton } from '@/components/ui/skeleton'
|
|
|
11
11
|
import { useRadius } from '@/hooks/useRadius'
|
|
12
12
|
import { cn } from '@/lib/utils'
|
|
13
13
|
import { useDensity } from '@/hooks/useDensity'
|
|
14
|
+
import { ROOT_SELECTOR } from '@/constants/tailwind'
|
|
14
15
|
|
|
15
16
|
interface ThreadListProps {
|
|
16
17
|
className?: string
|
|
@@ -23,7 +24,8 @@ export const ThreadList: FC<ThreadListProps> = ({ className }) => {
|
|
|
23
24
|
className={cn(
|
|
24
25
|
'aui-root aui-thread-list-root bg-background flex flex-col items-stretch',
|
|
25
26
|
d('gap-sm'),
|
|
26
|
-
className
|
|
27
|
+
className,
|
|
28
|
+
ROOT_SELECTOR
|
|
27
29
|
)}
|
|
28
30
|
>
|
|
29
31
|
<div
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
ChevronRightIcon,
|
|
7
7
|
CopyIcon,
|
|
8
8
|
PencilIcon,
|
|
9
|
-
RefreshCwIcon,
|
|
10
9
|
Settings2,
|
|
11
10
|
Square,
|
|
12
11
|
} from 'lucide-react'
|
|
@@ -52,19 +51,18 @@ import {
|
|
|
52
51
|
} from '../ui/tooltip'
|
|
53
52
|
import { ToolGroup } from './tool-group'
|
|
54
53
|
|
|
55
|
-
const
|
|
54
|
+
const StaticSessionWarning = () => (
|
|
56
55
|
<div className="m-2 rounded-md border border-amber-500 bg-amber-100 px-4 py-3 text-sm text-amber-800 dark:border-amber-600 dark:bg-amber-900/30 dark:text-amber-200">
|
|
57
|
-
<strong>Warning:</strong> You are using
|
|
58
|
-
Please{' '}
|
|
56
|
+
<strong>Warning:</strong> You are using a static session token in the
|
|
57
|
+
client. It will expire shortly. Please{' '}
|
|
59
58
|
<a
|
|
60
59
|
href="https://github.com/speakeasy-api/gram/tree/main/elements#setting-up-your-backend"
|
|
61
60
|
target="_blank"
|
|
62
61
|
rel="noopener noreferrer"
|
|
63
62
|
className="text-amber-700 underline hover:text-amber-800 dark:text-amber-300 dark:hover:text-amber-200"
|
|
64
63
|
>
|
|
65
|
-
set up a session endpoint
|
|
66
|
-
</a>
|
|
67
|
-
before deploying to production.
|
|
64
|
+
set up a session endpoint to avoid this warning.
|
|
65
|
+
</a>
|
|
68
66
|
</div>
|
|
69
67
|
)
|
|
70
68
|
|
|
@@ -77,7 +75,7 @@ export const Thread: FC<ThreadProps> = ({ className }) => {
|
|
|
77
75
|
const d = useDensity()
|
|
78
76
|
const { config } = useElements()
|
|
79
77
|
const components = config.components ?? {}
|
|
80
|
-
const
|
|
78
|
+
const showStaticSessionWarning = config.api && 'sessionToken' in config.api
|
|
81
79
|
|
|
82
80
|
return (
|
|
83
81
|
<LazyMotion features={domAnimation}>
|
|
@@ -103,7 +101,7 @@ export const Thread: FC<ThreadProps> = ({ className }) => {
|
|
|
103
101
|
)}
|
|
104
102
|
</ThreadPrimitive.If>
|
|
105
103
|
|
|
106
|
-
{
|
|
104
|
+
{showStaticSessionWarning && <StaticSessionWarning />}
|
|
107
105
|
|
|
108
106
|
<ThreadPrimitive.Messages
|
|
109
107
|
components={{
|
|
@@ -495,7 +493,7 @@ const AssistantMessage: FC = () => {
|
|
|
495
493
|
</div>
|
|
496
494
|
|
|
497
495
|
<div className="aui-assistant-message-footer mt-2 ml-2 flex">
|
|
498
|
-
<BranchPicker />
|
|
496
|
+
{/* <BranchPicker /> */}
|
|
499
497
|
<AssistantActionBar />
|
|
500
498
|
</div>
|
|
501
499
|
</div>
|
|
@@ -525,11 +523,11 @@ const AssistantActionBar: FC = () => {
|
|
|
525
523
|
</MessagePrimitive.If>
|
|
526
524
|
</TooltipIconButton>
|
|
527
525
|
</ActionBarPrimitive.Copy>
|
|
528
|
-
<ActionBarPrimitive.Reload asChild>
|
|
526
|
+
{/* <ActionBarPrimitive.Reload asChild>
|
|
529
527
|
<TooltipIconButton tooltip="Refresh">
|
|
530
528
|
<RefreshCwIcon />
|
|
531
529
|
</TooltipIconButton>
|
|
532
|
-
</ActionBarPrimitive.Reload>
|
|
530
|
+
</ActionBarPrimitive.Reload> */}
|
|
533
531
|
</ActionBarPrimitive.Root>
|
|
534
532
|
)
|
|
535
533
|
}
|
|
@@ -3,6 +3,7 @@ import * as DialogPrimitive from '@radix-ui/react-dialog'
|
|
|
3
3
|
import { XIcon } from 'lucide-react'
|
|
4
4
|
|
|
5
5
|
import { cn } from '@/lib/utils'
|
|
6
|
+
import { usePortalContainer } from '@/hooks/usePortalContainer'
|
|
6
7
|
|
|
7
8
|
function Dialog({
|
|
8
9
|
...props
|
|
@@ -17,9 +18,17 @@ function DialogTrigger({
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
function DialogPortal({
|
|
21
|
+
container,
|
|
20
22
|
...props
|
|
21
23
|
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
22
|
-
|
|
24
|
+
const portalContainer = usePortalContainer()
|
|
25
|
+
return (
|
|
26
|
+
<DialogPrimitive.Portal
|
|
27
|
+
data-slot="dialog-portal"
|
|
28
|
+
container={container ?? portalContainer}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
)
|
|
23
32
|
}
|
|
24
33
|
|
|
25
34
|
function DialogClose({
|
|
@@ -22,18 +22,16 @@ function PopoverContent({
|
|
|
22
22
|
...props
|
|
23
23
|
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
24
24
|
return (
|
|
25
|
-
<PopoverPrimitive.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
/>
|
|
36
|
-
</PopoverPrimitive.Portal>
|
|
25
|
+
<PopoverPrimitive.Content
|
|
26
|
+
data-slot="popover-content"
|
|
27
|
+
align={align}
|
|
28
|
+
sideOffset={sideOffset}
|
|
29
|
+
className={cn(
|
|
30
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-20 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
37
35
|
)
|
|
38
36
|
}
|
|
39
37
|
|
|
@@ -4,6 +4,7 @@ import * as React from 'react'
|
|
|
4
4
|
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
|
|
5
5
|
|
|
6
6
|
import { cn } from '@/lib/utils'
|
|
7
|
+
import { usePortalContainer } from '@/hooks/usePortalContainer'
|
|
7
8
|
|
|
8
9
|
function TooltipProvider({
|
|
9
10
|
delayDuration = 0,
|
|
@@ -38,10 +39,14 @@ function TooltipContent({
|
|
|
38
39
|
className,
|
|
39
40
|
sideOffset = 0,
|
|
40
41
|
children,
|
|
42
|
+
container,
|
|
41
43
|
...props
|
|
42
|
-
}: React.ComponentProps<typeof TooltipPrimitive.Content>
|
|
44
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content> & {
|
|
45
|
+
container?: HTMLElement | null
|
|
46
|
+
}) {
|
|
47
|
+
const portalContainer = usePortalContainer()
|
|
43
48
|
return (
|
|
44
|
-
<TooltipPrimitive.Portal>
|
|
49
|
+
<TooltipPrimitive.Portal container={container ?? portalContainer}>
|
|
45
50
|
<TooltipPrimitive.Content
|
|
46
51
|
data-slot="tooltip-content"
|
|
47
52
|
sideOffset={sideOffset}
|
|
@@ -2,6 +2,7 @@ import { FrontendTools } from '@/components/FrontendTools'
|
|
|
2
2
|
import { useMCPTools } from '@/hooks/useMCPTools'
|
|
3
3
|
import { useToolApproval } from '@/hooks/useToolApproval'
|
|
4
4
|
import { getApiUrl } from '@/lib/api'
|
|
5
|
+
import { initErrorTracking, trackError } from '@/lib/errorTracking'
|
|
5
6
|
import { MODELS } from '@/lib/models'
|
|
6
7
|
import {
|
|
7
8
|
clearFrontendToolApprovalConfig,
|
|
@@ -125,6 +126,15 @@ const ElementsProviderWithApproval = ({
|
|
|
125
126
|
plugins
|
|
126
127
|
)
|
|
127
128
|
|
|
129
|
+
// Initialize error tracking on mount
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
initErrorTracking({
|
|
132
|
+
enabled: config.errorTracking?.enabled,
|
|
133
|
+
projectSlug: config.projectSlug,
|
|
134
|
+
variant: config.variant,
|
|
135
|
+
})
|
|
136
|
+
}, [])
|
|
137
|
+
|
|
128
138
|
const { data: mcpTools } = useMCPTools({
|
|
129
139
|
auth,
|
|
130
140
|
mcp: config.mcp,
|
|
@@ -157,7 +167,7 @@ const ElementsProviderWithApproval = ({
|
|
|
157
167
|
|
|
158
168
|
// Set up frontend tool approval config for runtime checking
|
|
159
169
|
useEffect(() => {
|
|
160
|
-
if (config.tools?.toolsRequiringApproval
|
|
170
|
+
if (config.tools?.toolsRequiringApproval) {
|
|
161
171
|
setFrontendToolApprovalConfig(
|
|
162
172
|
getApprovalHelpers(),
|
|
163
173
|
config.tools.toolsRequiringApproval
|
|
@@ -249,12 +259,14 @@ const ElementsProviderWithApproval = ({
|
|
|
249
259
|
abortSignal,
|
|
250
260
|
onError: ({ error }) => {
|
|
251
261
|
console.error('Stream error in onError callback:', error)
|
|
262
|
+
trackError(error, { source: 'streaming' })
|
|
252
263
|
},
|
|
253
264
|
})
|
|
254
265
|
|
|
255
266
|
return result.toUIMessageStream()
|
|
256
267
|
} catch (error) {
|
|
257
268
|
console.error('Error creating stream:', error)
|
|
269
|
+
trackError(error, { source: 'stream-creation' })
|
|
258
270
|
throw error
|
|
259
271
|
}
|
|
260
272
|
},
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { type RefObject } from 'react'
|
|
4
|
+
import { PortalContainerContext } from './portal-container-context'
|
|
5
|
+
|
|
6
|
+
export { PortalContainerContext }
|
|
7
|
+
|
|
8
|
+
export function PortalContainerProvider({
|
|
9
|
+
containerRef,
|
|
10
|
+
children,
|
|
11
|
+
}: {
|
|
12
|
+
containerRef: RefObject<HTMLElement | null>
|
|
13
|
+
children: React.ReactNode
|
|
14
|
+
}) {
|
|
15
|
+
return (
|
|
16
|
+
<PortalContainerContext.Provider value={containerRef}>
|
|
17
|
+
{children}
|
|
18
|
+
</PortalContainerContext.Provider>
|
|
19
|
+
)
|
|
20
|
+
}
|
package/src/global.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
@import
|
|
2
|
-
@import
|
|
3
|
-
@
|
|
1
|
+
@import 'tw-animate-css';
|
|
2
|
+
@import 'tw-shimmer';
|
|
3
|
+
@layer theme, base, components, utilities;
|
|
4
|
+
@import 'tailwindcss/theme.css' layer(theme);
|
|
4
5
|
|
|
5
6
|
@custom-variant dark (&:is(.dark *));
|
|
6
7
|
|
|
@@ -42,7 +43,20 @@
|
|
|
42
43
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
:root
|
|
46
|
+
/* Scope ALL variables to .gram-elements instead of :root */
|
|
47
|
+
.gram-elements {
|
|
48
|
+
/* Scoped preflight/base styles */
|
|
49
|
+
font-family:
|
|
50
|
+
ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
|
51
|
+
'Segoe UI Symbol', 'Noto Color Emoji';
|
|
52
|
+
font-feature-settings: normal;
|
|
53
|
+
font-variation-settings: normal;
|
|
54
|
+
-webkit-font-smoothing: antialiased;
|
|
55
|
+
-moz-osx-font-smoothing: grayscale;
|
|
56
|
+
line-height: 1.5;
|
|
57
|
+
-webkit-tap-highlight-color: transparent;
|
|
58
|
+
tab-size: 4;
|
|
59
|
+
|
|
46
60
|
/* Theme: Radius - set via data-radius attribute */
|
|
47
61
|
--radius: 0.625rem;
|
|
48
62
|
--background: oklch(1 0 0);
|
|
@@ -78,7 +92,9 @@
|
|
|
78
92
|
--sidebar-ring: oklch(0.705 0.015 286.067);
|
|
79
93
|
}
|
|
80
94
|
|
|
81
|
-
.
|
|
95
|
+
/* Dark mode scoped to .gram-elements */
|
|
96
|
+
.gram-elements.dark,
|
|
97
|
+
.dark .gram-elements {
|
|
82
98
|
--background: oklch(0.141 0.005 285.823);
|
|
83
99
|
--foreground: oklch(0.985 0 0);
|
|
84
100
|
--card: oklch(0.21 0.006 285.885);
|
|
@@ -113,24 +129,121 @@
|
|
|
113
129
|
}
|
|
114
130
|
|
|
115
131
|
@layer base {
|
|
116
|
-
|
|
117
|
-
@
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
132
|
+
.gram-elements {
|
|
133
|
+
@tailwind utilities;
|
|
134
|
+
|
|
135
|
+
/* We can't use tailwind's preflight styles here because we need to scope them to .gram-elements so therefore we just include a version of them inline here */
|
|
136
|
+
*,
|
|
137
|
+
*::before,
|
|
138
|
+
*::after {
|
|
139
|
+
box-sizing: border-box;
|
|
140
|
+
border-width: 0;
|
|
141
|
+
border-style: solid;
|
|
142
|
+
@apply border-border outline-ring/50;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Reset margins and padding for common elements */
|
|
146
|
+
h1,
|
|
147
|
+
h2,
|
|
148
|
+
h3,
|
|
149
|
+
h4,
|
|
150
|
+
h5,
|
|
151
|
+
h6,
|
|
152
|
+
p,
|
|
153
|
+
blockquote,
|
|
154
|
+
pre,
|
|
155
|
+
ul,
|
|
156
|
+
ol,
|
|
157
|
+
figure {
|
|
158
|
+
margin: 0;
|
|
159
|
+
padding: 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* List style reset */
|
|
163
|
+
ul,
|
|
164
|
+
ol {
|
|
165
|
+
list-style: none;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Image defaults */
|
|
169
|
+
img,
|
|
170
|
+
svg,
|
|
171
|
+
video,
|
|
172
|
+
canvas,
|
|
173
|
+
audio,
|
|
174
|
+
iframe,
|
|
175
|
+
embed,
|
|
176
|
+
object {
|
|
177
|
+
display: block;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
img,
|
|
181
|
+
video {
|
|
182
|
+
max-width: 100%;
|
|
183
|
+
height: auto;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/* Button/input reset */
|
|
187
|
+
button,
|
|
188
|
+
input,
|
|
189
|
+
optgroup,
|
|
190
|
+
select,
|
|
191
|
+
textarea {
|
|
192
|
+
font-family: inherit;
|
|
193
|
+
font-feature-settings: inherit;
|
|
194
|
+
font-variation-settings: inherit;
|
|
195
|
+
font-size: 100%;
|
|
196
|
+
font-weight: inherit;
|
|
197
|
+
line-height: inherit;
|
|
198
|
+
letter-spacing: inherit;
|
|
199
|
+
color: inherit;
|
|
200
|
+
margin: 0;
|
|
201
|
+
padding: 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
button,
|
|
205
|
+
select {
|
|
206
|
+
text-transform: none;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
button,
|
|
210
|
+
input:where([type='button']),
|
|
211
|
+
input:where([type='reset']),
|
|
212
|
+
input:where([type='submit']) {
|
|
213
|
+
appearance: button;
|
|
214
|
+
-webkit-appearance: button;
|
|
215
|
+
background-color: transparent;
|
|
216
|
+
background-image: none;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
a {
|
|
220
|
+
color: inherit;
|
|
221
|
+
text-decoration: inherit;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/* Table reset */
|
|
225
|
+
table {
|
|
226
|
+
text-indent: 0;
|
|
227
|
+
border-color: inherit;
|
|
228
|
+
border-collapse: collapse;
|
|
229
|
+
}
|
|
121
230
|
}
|
|
122
231
|
}
|
|
123
232
|
|
|
124
|
-
/* Theme: Radius variants via data attribute */
|
|
125
|
-
[data-radius='sharp']
|
|
233
|
+
/* Theme: Radius variants via data attribute - scoped */
|
|
234
|
+
.gram-elements[data-radius='sharp'],
|
|
235
|
+
[data-radius='sharp'] .gram-elements {
|
|
126
236
|
--radius: 0.25rem;
|
|
127
237
|
}
|
|
128
|
-
[data-radius='soft']
|
|
238
|
+
.gram-elements[data-radius='soft'],
|
|
239
|
+
[data-radius='soft'] .gram-elements {
|
|
129
240
|
--radius: 0.625rem;
|
|
130
241
|
}
|
|
131
|
-
[data-radius='round']
|
|
242
|
+
.gram-elements[data-radius='round'],
|
|
243
|
+
[data-radius='round'] .gram-elements {
|
|
132
244
|
--radius: 1rem;
|
|
133
245
|
}
|
|
134
|
-
[data-radius='pill']
|
|
246
|
+
.gram-elements[data-radius='pill'],
|
|
247
|
+
[data-radius='pill'] .gram-elements {
|
|
135
248
|
--radius: 9999px;
|
|
136
|
-
}
|
|
249
|
+
}
|
package/src/hooks/useAuth.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { hasExplicitSessionAuth,
|
|
1
|
+
import { hasExplicitSessionAuth, isStaticSessionAuth } from '@/lib/auth'
|
|
2
|
+
import { useMemo } from 'react'
|
|
2
3
|
import { ApiConfig } from '../types'
|
|
3
4
|
import { useSession } from './useSession'
|
|
4
|
-
import { useMemo } from 'react'
|
|
5
5
|
|
|
6
6
|
export type Auth =
|
|
7
7
|
| {
|
|
@@ -38,33 +38,23 @@ export const useAuth = ({
|
|
|
38
38
|
projectSlug: string
|
|
39
39
|
}): Auth => {
|
|
40
40
|
const getSession = useMemo(() => {
|
|
41
|
-
if (
|
|
42
|
-
return
|
|
41
|
+
if (isStaticSessionAuth(auth)) {
|
|
42
|
+
return () => Promise.resolve(auth.sessionToken)
|
|
43
43
|
}
|
|
44
|
-
return !
|
|
44
|
+
return !isStaticSessionAuth(auth) && hasExplicitSessionAuth(auth)
|
|
45
45
|
? auth.sessionFn
|
|
46
46
|
: defaultGetSession
|
|
47
47
|
}, [auth])
|
|
48
|
+
|
|
48
49
|
// The session request is only neccessary if we are not using an API key auth
|
|
49
50
|
// configuration. If a custom session fetcher is provided, we use it,
|
|
50
51
|
// otherwise we fallback to the default session fetcher
|
|
51
52
|
const session = useSession({
|
|
52
53
|
// We want to check it's NOT API key auth, as the default auth scheme is session auth (if the user hasn't provided an explicit API config, we have a session auth config by default)
|
|
53
|
-
enabled: !isApiKeyAuth(auth),
|
|
54
54
|
getSession,
|
|
55
55
|
projectSlug,
|
|
56
56
|
})
|
|
57
57
|
|
|
58
|
-
if (isApiKeyAuth(auth)) {
|
|
59
|
-
return {
|
|
60
|
-
headers: {
|
|
61
|
-
'Gram-Project': projectSlug,
|
|
62
|
-
'Gram-Key': auth.UNSAFE_apiKey,
|
|
63
|
-
},
|
|
64
|
-
isLoading: false,
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
58
|
return !session
|
|
69
59
|
? {
|
|
70
60
|
isLoading: true,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useContext } from 'react'
|
|
4
|
+
import { PortalContainerContext } from '@/contexts/portal-container-context'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Because we do not want Tailwind to leak from the Elements library, and
|
|
8
|
+
* because some UI elements such as Dialogs and Tooltips need to be rendered in
|
|
9
|
+
* a different container than the root element, we need to use a portal
|
|
10
|
+
* container, which renders any tooltips, dialogs etc within the .gram-elements
|
|
11
|
+
* scope so that they still inherit the Elements CSS
|
|
12
|
+
*/
|
|
13
|
+
export function usePortalContainer(): HTMLElement | null {
|
|
14
|
+
const ref = useContext(PortalContainerContext)
|
|
15
|
+
return ref?.current ?? null
|
|
16
|
+
}
|