@agents24/chat-react 0.4.0 → 0.5.1
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 +92 -18
- package/compatibility.json +10 -10
- package/dist/chunk-SSUO4EPD.js +189 -0
- package/dist/chunk-SSUO4EPD.js.map +1 -0
- package/dist/chunk-ZCNHLFRB.js +108 -0
- package/dist/chunk-ZCNHLFRB.js.map +1 -0
- package/dist/index.cjs +112 -95
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +362 -68
- package/dist/index.js.map +1 -1
- package/dist/mcp-oauth.d.ts +13 -0
- package/dist/runtime/index.cjs +594 -0
- package/dist/runtime/index.cjs.map +1 -0
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +458 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/input-contract.d.ts +20 -0
- package/dist/runtime/use-agent-chat-runtime.d.ts +83 -0
- package/dist/scaffold/app.d.ts +30 -0
- package/dist/scaffold/components/chat/chat-composer.d.ts +21 -0
- package/dist/scaffold/components/chat/chat-message.d.ts +21 -0
- package/dist/scaffold/components/chat/chat-shell.d.ts +8 -0
- package/dist/scaffold/components/chat/collapsible-user-message.d.ts +3 -0
- package/dist/scaffold/components/chat/external-link-dialog.d.ts +2 -0
- package/dist/scaffold/components/chat/identity-control.d.ts +4 -0
- package/dist/scaffold/components/chat/message-parts.d.ts +12 -0
- package/dist/scaffold/components/chat/theme-menu.d.ts +1 -0
- package/dist/scaffold/components/chat/thread-sidebar.d.ts +16 -0
- package/dist/scaffold/components/chat/timeline-loading.d.ts +7 -0
- package/dist/scaffold/components/chat/turn-outline.d.ts +4 -0
- package/dist/scaffold/components/theme-provider.d.ts +20 -0
- package/dist/scaffold/components/ui/attachment.d.ts +24 -0
- package/dist/scaffold/components/ui/bubble.d.ts +17 -0
- package/dist/scaffold/components/ui/button-group.d.ts +11 -0
- package/dist/scaffold/components/ui/button.d.ts +10 -0
- package/dist/scaffold/components/ui/dialog.d.ts +17 -0
- package/dist/scaffold/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/scaffold/components/ui/input.d.ts +3 -0
- package/dist/scaffold/components/ui/marker.d.ts +11 -0
- package/dist/scaffold/components/ui/message-scroller.d.ts +10 -0
- package/dist/scaffold/components/ui/message.d.ts +10 -0
- package/dist/scaffold/components/ui/popover.d.ts +6 -0
- package/dist/scaffold/components/ui/select.d.ts +8 -0
- package/dist/scaffold/components/ui/separator.d.ts +4 -0
- package/dist/scaffold/components/ui/sheet.d.ts +14 -0
- package/dist/scaffold/components/ui/sidebar.d.ts +69 -0
- package/dist/scaffold/components/ui/skeleton.d.ts +2 -0
- package/dist/scaffold/components/ui/textarea.d.ts +3 -0
- package/dist/scaffold/components/ui/tooltip.d.ts +15 -0
- package/dist/scaffold/hooks/use-mobile.d.ts +1 -0
- package/dist/scaffold/identity.d.ts +10 -0
- package/dist/scaffold/index.cjs +2270 -0
- package/dist/scaffold/index.cjs.map +1 -0
- package/dist/scaffold/index.d.ts +14 -0
- package/dist/scaffold/index.js +2244 -0
- package/dist/scaffold/index.js.map +1 -0
- package/dist/scaffold/lib/utils.d.ts +2 -0
- package/dist/styles.css +143 -298
- package/dist/types.d.ts +3 -13
- package/dist/ui/adapters.d.ts +1 -1
- package/dist/ui/agent-chat-actions.d.ts +12 -5
- package/dist/ui/agent-chat-composer.d.ts +2 -1
- package/dist/ui/agent-chat-context-compression-row.d.ts +5 -0
- package/dist/ui/agent-chat-context-status.d.ts +13 -0
- package/dist/ui/agent-chat-message.d.ts +7 -5
- package/dist/ui/agent-response-timeline.d.ts +29 -7
- package/dist/ui/ask-user-interaction-state.d.ts +20 -0
- package/dist/ui/ask-user-interaction.d.ts +8 -0
- package/dist/ui/index.cjs +1392 -272
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.ts +5 -0
- package/dist/ui/index.js +2380 -65
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/tool-sessions.d.ts +70 -0
- package/dist/ui/use-audio-recorder.d.ts +8 -0
- package/package.json +27 -12
- package/scaffold/components.json +25 -0
- package/scaffold/manifest.json +28 -0
- package/scaffold/src/app.tsx +71 -0
- package/scaffold/src/chat.css +54 -0
- package/scaffold/src/components/chat/chat-composer.tsx +237 -0
- package/scaffold/src/components/chat/chat-message.tsx +76 -0
- package/scaffold/src/components/chat/chat-shell.tsx +257 -0
- package/scaffold/src/components/chat/collapsible-user-message.tsx +37 -0
- package/scaffold/src/components/chat/external-link-dialog.tsx +48 -0
- package/scaffold/src/components/chat/identity-control.tsx +69 -0
- package/scaffold/src/components/chat/message-parts.tsx +83 -0
- package/scaffold/src/components/chat/theme-menu.tsx +79 -0
- package/scaffold/src/components/chat/thread-sidebar.tsx +114 -0
- package/scaffold/src/components/chat/timeline-loading.ts +17 -0
- package/scaffold/src/components/chat/turn-outline.tsx +73 -0
- package/scaffold/src/components/theme-provider.tsx +91 -0
- package/scaffold/src/components/ui/attachment.tsx +204 -0
- package/scaffold/src/components/ui/bubble.tsx +125 -0
- package/scaffold/src/components/ui/button-group.tsx +83 -0
- package/scaffold/src/components/ui/button.tsx +65 -0
- package/scaffold/src/components/ui/dialog.tsx +171 -0
- package/scaffold/src/components/ui/dropdown-menu.tsx +271 -0
- package/scaffold/src/components/ui/input.tsx +19 -0
- package/scaffold/src/components/ui/marker.tsx +69 -0
- package/scaffold/src/components/ui/message-scroller.tsx +129 -0
- package/scaffold/src/components/ui/message.tsx +92 -0
- package/scaffold/src/components/ui/popover.tsx +40 -0
- package/scaffold/src/components/ui/select.tsx +92 -0
- package/scaffold/src/components/ui/separator.tsx +28 -0
- package/scaffold/src/components/ui/sheet.tsx +150 -0
- package/scaffold/src/components/ui/sidebar.tsx +677 -0
- package/scaffold/src/components/ui/skeleton.tsx +13 -0
- package/scaffold/src/components/ui/textarea.tsx +18 -0
- package/scaffold/src/components/ui/tooltip.tsx +56 -0
- package/scaffold/src/hooks/use-mobile.ts +24 -0
- package/scaffold/src/identity.ts +17 -0
- package/scaffold/src/index.css +222 -0
- package/scaffold/src/index.tsx +39 -0
- package/scaffold/src/lib/utils.ts +6 -0
- package/scaffold/styles.css +3 -0
- package/dist/chunk-CHAU7FNW.js +0 -140
- package/dist/chunk-CHAU7FNW.js.map +0 -1
- package/dist/chunk-LI67M74F.js +0 -445
- package/dist/chunk-LI67M74F.js.map +0 -1
- package/dist/chunk-NLEOWTZG.js +0 -1327
- package/dist/chunk-NLEOWTZG.js.map +0 -1
- package/dist/renderers.d.ts +0 -10
- package/dist/templates/agent-chat-app.d.ts +0 -18
- package/dist/templates/agent-chat-layout.d.ts +0 -69
- package/dist/templates/agent-chat-shell.d.ts +0 -37
- package/dist/templates/index.cjs +0 -2476
- package/dist/templates/index.cjs.map +0 -1
- package/dist/templates/index.d.ts +0 -3
- package/dist/templates/index.js +0 -723
- package/dist/templates/index.js.map +0 -1
|
@@ -0,0 +1,2270 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// scaffold/src/index.tsx
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
Agents24ChatScaffold: () => Agents24ChatScaffold,
|
|
34
|
+
Agents24ChatScaffoldApp: () => App,
|
|
35
|
+
Agents24ChatThemeProvider: () => ThemeProvider,
|
|
36
|
+
Agents24ChatTooltipProvider: () => TooltipProvider
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(src_exports);
|
|
39
|
+
|
|
40
|
+
// scaffold/src/app.tsx
|
|
41
|
+
var import_runtime3 = require("@agents24/chat-react/runtime");
|
|
42
|
+
var import_react3 = require("@agents24/react");
|
|
43
|
+
|
|
44
|
+
// scaffold/src/components/chat/chat-shell.tsx
|
|
45
|
+
var import_runtime2 = require("@agents24/chat-react/runtime");
|
|
46
|
+
var import_lucide_react12 = require("lucide-react");
|
|
47
|
+
|
|
48
|
+
// scaffold/src/components/chat/chat-composer.tsx
|
|
49
|
+
var import_lucide_react2 = require("lucide-react");
|
|
50
|
+
var React2 = __toESM(require("react"), 1);
|
|
51
|
+
var import_ui = require("@agents24/chat-react/ui");
|
|
52
|
+
var import_runtime = require("@agents24/chat-react/runtime");
|
|
53
|
+
|
|
54
|
+
// scaffold/src/components/ui/button.tsx
|
|
55
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
56
|
+
var import_radix_ui = require("radix-ui");
|
|
57
|
+
|
|
58
|
+
// scaffold/src/lib/utils.ts
|
|
59
|
+
var import_clsx = require("clsx");
|
|
60
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
61
|
+
function cn(...inputs) {
|
|
62
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// scaffold/src/components/ui/button.tsx
|
|
66
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
67
|
+
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
68
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
69
|
+
{
|
|
70
|
+
variants: {
|
|
71
|
+
variant: {
|
|
72
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
73
|
+
outline: "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:bg-transparent dark:hover:bg-input/30",
|
|
74
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
75
|
+
ghost: "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
76
|
+
destructive: "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
77
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
78
|
+
},
|
|
79
|
+
size: {
|
|
80
|
+
default: "h-9 gap-1.5 px-3 has-data-[icon=inline-end]:pr-2.5 has-data-[icon=inline-start]:pl-2.5",
|
|
81
|
+
xs: "h-6 gap-1 px-2.5 text-xs has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2 [&_svg:not([class*='size-'])]:size-3",
|
|
82
|
+
sm: "h-8 gap-1 px-3 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
83
|
+
lg: "h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3",
|
|
84
|
+
icon: "size-9",
|
|
85
|
+
"icon-xs": "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
86
|
+
"icon-sm": "size-8",
|
|
87
|
+
"icon-lg": "size-10"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
defaultVariants: {
|
|
91
|
+
variant: "default",
|
|
92
|
+
size: "default"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
function Button({
|
|
97
|
+
className,
|
|
98
|
+
variant = "default",
|
|
99
|
+
size = "default",
|
|
100
|
+
asChild = false,
|
|
101
|
+
...props
|
|
102
|
+
}) {
|
|
103
|
+
const Comp = asChild ? import_radix_ui.Slot.Root : "button";
|
|
104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
105
|
+
Comp,
|
|
106
|
+
{
|
|
107
|
+
"data-slot": "button",
|
|
108
|
+
"data-variant": variant,
|
|
109
|
+
"data-size": size,
|
|
110
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
111
|
+
...props
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// scaffold/src/components/ui/select.tsx
|
|
117
|
+
var import_lucide_react = require("lucide-react");
|
|
118
|
+
var import_radix_ui2 = require("radix-ui");
|
|
119
|
+
|
|
120
|
+
// scaffold/src/components/theme-provider.tsx
|
|
121
|
+
var React = __toESM(require("react"), 1);
|
|
122
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
123
|
+
var ThemeContext = React.createContext(null);
|
|
124
|
+
var storageKey = "agents24-chat-appearance";
|
|
125
|
+
function storedAppearance() {
|
|
126
|
+
try {
|
|
127
|
+
const stored = window.localStorage.getItem(storageKey);
|
|
128
|
+
return stored === "light" || stored === "dark" || stored === "system" ? stored : "system";
|
|
129
|
+
} catch {
|
|
130
|
+
return "system";
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function ThemeProvider({
|
|
134
|
+
children,
|
|
135
|
+
controller,
|
|
136
|
+
theme = "soft"
|
|
137
|
+
}) {
|
|
138
|
+
const [internalAppearance, setInternalAppearance] = React.useState("system");
|
|
139
|
+
const [resolvedAppearance, setResolvedAppearance] = React.useState("light");
|
|
140
|
+
const [mounted, setMounted] = React.useState(false);
|
|
141
|
+
const [portalContainer, setPortalContainer] = React.useState(null);
|
|
142
|
+
const appearance = controller?.appearance ?? internalAppearance;
|
|
143
|
+
React.useEffect(() => {
|
|
144
|
+
if (!controller) setInternalAppearance(storedAppearance());
|
|
145
|
+
setMounted(true);
|
|
146
|
+
}, [controller]);
|
|
147
|
+
React.useEffect(() => {
|
|
148
|
+
if (!mounted || typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
149
|
+
const media = window.matchMedia("(prefers-color-scheme: dark)");
|
|
150
|
+
const apply = () => setResolvedAppearance(
|
|
151
|
+
appearance === "system" ? media.matches ? "dark" : "light" : appearance
|
|
152
|
+
);
|
|
153
|
+
apply();
|
|
154
|
+
media.addEventListener("change", apply);
|
|
155
|
+
return () => media.removeEventListener("change", apply);
|
|
156
|
+
}, [appearance, mounted]);
|
|
157
|
+
const change = React.useCallback((next) => {
|
|
158
|
+
if (controller) {
|
|
159
|
+
controller.setAppearance(next);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
window.localStorage.setItem(storageKey, next);
|
|
164
|
+
} catch {
|
|
165
|
+
}
|
|
166
|
+
setInternalAppearance(next);
|
|
167
|
+
}, [controller]);
|
|
168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ThemeContext.Provider, { value: { appearance, portalContainer, setAppearance: change }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
169
|
+
"div",
|
|
170
|
+
{
|
|
171
|
+
ref: setPortalContainer,
|
|
172
|
+
className: `${resolvedAppearance} size-full`,
|
|
173
|
+
"data-agents24-theme": theme,
|
|
174
|
+
"data-agents24-theme-root": "",
|
|
175
|
+
children
|
|
176
|
+
}
|
|
177
|
+
) });
|
|
178
|
+
}
|
|
179
|
+
function useTheme() {
|
|
180
|
+
const context = React.useContext(ThemeContext);
|
|
181
|
+
if (!context) throw new Error("useTheme must be used inside ThemeProvider");
|
|
182
|
+
return context;
|
|
183
|
+
}
|
|
184
|
+
function useThemePortalContainer() {
|
|
185
|
+
return useTheme().portalContainer;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// scaffold/src/components/ui/select.tsx
|
|
189
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
190
|
+
function Select(props) {
|
|
191
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.Root, { "data-slot": "select", ...props });
|
|
192
|
+
}
|
|
193
|
+
function SelectValue(props) {
|
|
194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.Value, { "data-slot": "select-value", ...props });
|
|
195
|
+
}
|
|
196
|
+
function SelectTrigger({
|
|
197
|
+
children,
|
|
198
|
+
className,
|
|
199
|
+
...props
|
|
200
|
+
}) {
|
|
201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
202
|
+
import_radix_ui2.Select.Trigger,
|
|
203
|
+
{
|
|
204
|
+
className: cn(
|
|
205
|
+
"flex h-8 w-full items-center justify-between gap-2 rounded-lg bg-transparent px-2.5 text-xs text-foreground outline-none transition-colors hover:bg-muted/50 focus-visible:bg-muted/50 disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground [&>span]:min-w-0 [&>span]:truncate",
|
|
206
|
+
className
|
|
207
|
+
),
|
|
208
|
+
"data-slot": "select-trigger",
|
|
209
|
+
...props,
|
|
210
|
+
children: [
|
|
211
|
+
children,
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.ChevronDownIcon, { className: "size-3.5 shrink-0 text-muted-foreground" }) })
|
|
213
|
+
]
|
|
214
|
+
}
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
function SelectContent({
|
|
218
|
+
align = "start",
|
|
219
|
+
children,
|
|
220
|
+
className,
|
|
221
|
+
sideOffset = 4,
|
|
222
|
+
...props
|
|
223
|
+
}) {
|
|
224
|
+
const container = useThemePortalContainer();
|
|
225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.Portal, { container: container || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
226
|
+
import_radix_ui2.Select.Content,
|
|
227
|
+
{
|
|
228
|
+
align,
|
|
229
|
+
className: cn(
|
|
230
|
+
"z-50 max-h-64 min-w-[var(--radix-select-trigger-width)] overflow-hidden rounded-xl border border-border/50 bg-popover p-1 text-popover-foreground shadow-md data-[side=bottom]:animate-in data-[side=bottom]:fade-in-0 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:animate-in data-[side=top]:fade-in-0 data-[side=top]:slide-in-from-bottom-1",
|
|
231
|
+
className
|
|
232
|
+
),
|
|
233
|
+
"data-slot": "select-content",
|
|
234
|
+
position: "popper",
|
|
235
|
+
sideOffset,
|
|
236
|
+
...props,
|
|
237
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.Viewport, { className: "max-h-60 overflow-y-auto p-0.5", children })
|
|
238
|
+
}
|
|
239
|
+
) });
|
|
240
|
+
}
|
|
241
|
+
function SelectItem({
|
|
242
|
+
children,
|
|
243
|
+
className,
|
|
244
|
+
...props
|
|
245
|
+
}) {
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
247
|
+
import_radix_ui2.Select.Item,
|
|
248
|
+
{
|
|
249
|
+
className: cn(
|
|
250
|
+
"relative flex cursor-default select-none items-center rounded-lg py-1.5 pr-8 pl-2 text-sm outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
251
|
+
className
|
|
252
|
+
),
|
|
253
|
+
"data-slot": "select-item",
|
|
254
|
+
...props,
|
|
255
|
+
children: [
|
|
256
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.ItemText, { className: "min-w-0 truncate", children }),
|
|
257
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_radix_ui2.Select.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.CheckIcon, { className: "size-3.5" }) }) })
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// scaffold/src/components/ui/textarea.tsx
|
|
264
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
265
|
+
function Textarea({ className, ...props }) {
|
|
266
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
267
|
+
"textarea",
|
|
268
|
+
{
|
|
269
|
+
"data-slot": "textarea",
|
|
270
|
+
className: cn(
|
|
271
|
+
"flex field-sizing-content min-h-16 w-full resize-none rounded-2xl border border-transparent bg-input/50 px-3 py-3 text-base transition-[color,box-shadow,background-color] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
272
|
+
className
|
|
273
|
+
),
|
|
274
|
+
...props
|
|
275
|
+
}
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// scaffold/src/components/ui/tooltip.tsx
|
|
280
|
+
var import_radix_ui3 = require("radix-ui");
|
|
281
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
282
|
+
function TooltipProvider({ children }) {
|
|
283
|
+
return children;
|
|
284
|
+
}
|
|
285
|
+
function Tooltip({ className, ...props }) {
|
|
286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
287
|
+
"span",
|
|
288
|
+
{
|
|
289
|
+
"data-slot": "tooltip",
|
|
290
|
+
className: cn("group/tooltip relative inline-flex", className),
|
|
291
|
+
...props
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
function TooltipTrigger({
|
|
296
|
+
asChild: _asChild,
|
|
297
|
+
...props
|
|
298
|
+
}) {
|
|
299
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_radix_ui3.Slot.Root, { "data-slot": "tooltip-trigger", ...props });
|
|
300
|
+
}
|
|
301
|
+
function TooltipContent({
|
|
302
|
+
className,
|
|
303
|
+
align: _align,
|
|
304
|
+
side = "top",
|
|
305
|
+
sideOffset: _sideOffset,
|
|
306
|
+
...props
|
|
307
|
+
}) {
|
|
308
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
309
|
+
"span",
|
|
310
|
+
{
|
|
311
|
+
role: "tooltip",
|
|
312
|
+
"data-side": side,
|
|
313
|
+
"data-slot": "tooltip-content",
|
|
314
|
+
className: cn(
|
|
315
|
+
"pointer-events-none absolute z-50 hidden w-max max-w-xs items-center gap-1.5 rounded-xl bg-foreground px-3 py-1.5 text-xs text-background group-hover/tooltip:inline-flex group-focus-within/tooltip:inline-flex",
|
|
316
|
+
"data-[side=top]:bottom-full data-[side=top]:left-1/2 data-[side=top]:mb-2 data-[side=top]:-translate-x-1/2",
|
|
317
|
+
"data-[side=bottom]:top-full data-[side=bottom]:left-1/2 data-[side=bottom]:mt-2 data-[side=bottom]:-translate-x-1/2",
|
|
318
|
+
"data-[side=left]:end-full data-[side=left]:top-1/2 data-[side=left]:me-2 data-[side=left]:-translate-y-1/2",
|
|
319
|
+
"data-[side=right]:start-full data-[side=right]:top-1/2 data-[side=right]:ms-2 data-[side=right]:-translate-y-1/2",
|
|
320
|
+
className
|
|
321
|
+
),
|
|
322
|
+
...props
|
|
323
|
+
}
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// scaffold/src/components/chat/chat-composer.tsx
|
|
328
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
329
|
+
function ChatComposer({
|
|
330
|
+
inputContract,
|
|
331
|
+
disabled,
|
|
332
|
+
contextWindow,
|
|
333
|
+
forceExpanded = false,
|
|
334
|
+
isCancelling = false,
|
|
335
|
+
isRunning,
|
|
336
|
+
modelId,
|
|
337
|
+
models,
|
|
338
|
+
onModelChange,
|
|
339
|
+
onStop,
|
|
340
|
+
onSubmit,
|
|
341
|
+
utilityRow = "inline"
|
|
342
|
+
}) {
|
|
343
|
+
const [text, setText] = React2.useState("");
|
|
344
|
+
const [files, setFiles] = React2.useState([]);
|
|
345
|
+
const [attachmentError, setAttachmentError] = React2.useState(null);
|
|
346
|
+
const inputRef = React2.useRef(null);
|
|
347
|
+
const textareaRef = React2.useRef(null);
|
|
348
|
+
const submittingRef = React2.useRef(false);
|
|
349
|
+
const draftRevisionRef = React2.useRef(0);
|
|
350
|
+
const attachmentMimeTypes = (0, import_runtime.inputMimeTypes)(inputContract);
|
|
351
|
+
const allowAttachments = attachmentMimeTypes.length > 0;
|
|
352
|
+
const recordingAllowed = inputContract.modalities.audio.recording_enabled;
|
|
353
|
+
const addRecording = React2.useCallback((file) => {
|
|
354
|
+
draftRevisionRef.current += 1;
|
|
355
|
+
setFiles((current) => [...current, file]);
|
|
356
|
+
}, []);
|
|
357
|
+
const recorder = (0, import_ui.useAudioRecorder)(addRecording);
|
|
358
|
+
const isExpanded = forceExpanded || text.includes("\n") || text.length > 62;
|
|
359
|
+
const validationError = (0, import_runtime.validateAgentChatSubmission)(
|
|
360
|
+
inputContract,
|
|
361
|
+
text,
|
|
362
|
+
files.map((file) => ({ data: file, mediaType: file.type }))
|
|
363
|
+
);
|
|
364
|
+
const modelSelector = models.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-fit max-w-40", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
365
|
+
Select,
|
|
366
|
+
{
|
|
367
|
+
disabled: disabled || isRunning,
|
|
368
|
+
onValueChange: onModelChange,
|
|
369
|
+
value: modelId || void 0,
|
|
370
|
+
children: [
|
|
371
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectTrigger, { "aria-label": "Runtime model", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectValue, { placeholder: "Model" }) }),
|
|
372
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectContent, { align: "start", children: models.map((model) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectItem, { value: model.id, children: model.label }, model.id)) })
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
) }) : null;
|
|
376
|
+
const hasContextWindow = Number.isFinite(Number(contextWindow?.max_tokens)) && Number(contextWindow?.max_tokens) > 0;
|
|
377
|
+
const showUtilityRow = utilityRow === "below";
|
|
378
|
+
const submit = async () => {
|
|
379
|
+
if (disabled || isRunning || submittingRef.current || validationError) return;
|
|
380
|
+
const value = text;
|
|
381
|
+
const selectedFiles = files;
|
|
382
|
+
const clearedRevision = draftRevisionRef.current + 1;
|
|
383
|
+
draftRevisionRef.current = clearedRevision;
|
|
384
|
+
submittingRef.current = true;
|
|
385
|
+
setText("");
|
|
386
|
+
setFiles([]);
|
|
387
|
+
textareaRef.current?.focus();
|
|
388
|
+
try {
|
|
389
|
+
await onSubmit(value, selectedFiles);
|
|
390
|
+
} catch {
|
|
391
|
+
if (draftRevisionRef.current === clearedRevision) {
|
|
392
|
+
draftRevisionRef.current += 1;
|
|
393
|
+
setText(value);
|
|
394
|
+
setFiles(selectedFiles);
|
|
395
|
+
}
|
|
396
|
+
} finally {
|
|
397
|
+
submittingRef.current = false;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
401
|
+
"div",
|
|
402
|
+
{
|
|
403
|
+
className: "mx-auto w-full max-w-3xl px-4 pb-[max(1rem,env(safe-area-inset-bottom))] sm:px-6",
|
|
404
|
+
"data-agents24-chat-composer": "",
|
|
405
|
+
children: [
|
|
406
|
+
allowAttachments && files.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mb-2 flex min-w-0 gap-2 overflow-x-auto", children: files.map((file, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex max-w-48 items-center gap-2 border bg-card px-2 py-1 text-xs", children: [
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate", children: file.name }),
|
|
408
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { variant: "ghost", size: "icon-xs", "aria-label": `Remove ${file.name}`, onClick: () => {
|
|
409
|
+
draftRevisionRef.current += 1;
|
|
410
|
+
setFiles((current) => current.filter((_, itemIndex) => itemIndex !== index));
|
|
411
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.X, {}) })
|
|
412
|
+
] }, `${file.name}-${index}`)) }),
|
|
413
|
+
attachmentError || recorder.error ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mb-2 text-xs text-destructive", role: "alert", children: attachmentError || recorder.error }) : null,
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
415
|
+
"div",
|
|
416
|
+
{
|
|
417
|
+
"data-expanded": isExpanded || void 0,
|
|
418
|
+
className: cn(
|
|
419
|
+
"agents24-composer-grid grid min-w-0 items-center gap-2 rounded-xl border bg-background shadow-sm",
|
|
420
|
+
isExpanded ? "p-2" : "p-1.5"
|
|
421
|
+
),
|
|
422
|
+
children: [
|
|
423
|
+
allowAttachments ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
424
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
425
|
+
"input",
|
|
426
|
+
{
|
|
427
|
+
ref: inputRef,
|
|
428
|
+
className: "sr-only",
|
|
429
|
+
type: "file",
|
|
430
|
+
multiple: true,
|
|
431
|
+
accept: attachmentMimeTypes.join(","),
|
|
432
|
+
onChange: (event) => {
|
|
433
|
+
const selected = Array.from(event.target.files ?? []);
|
|
434
|
+
const accepted = selected.filter((file) => attachmentMimeTypes.includes((0, import_runtime.canonicalInputMimeType)(file.type)));
|
|
435
|
+
draftRevisionRef.current += 1;
|
|
436
|
+
setFiles((current) => [...current, ...accepted]);
|
|
437
|
+
setAttachmentError(
|
|
438
|
+
accepted.length === selected.length ? null : "One or more selected file types are not supported by this Agent."
|
|
439
|
+
);
|
|
440
|
+
event.currentTarget.value = "";
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
),
|
|
444
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "agents24-composer-attach flex min-w-0 items-center", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { className: "bg-muted/50 text-muted-foreground hover:bg-muted hover:text-foreground", variant: "ghost", size: "icon", "aria-label": "Attach files", disabled: disabled || isRunning, onClick: () => inputRef.current?.click(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": true, children: "+" }) }) })
|
|
445
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", className: "agents24-composer-attach" }),
|
|
446
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
447
|
+
Textarea,
|
|
448
|
+
{
|
|
449
|
+
ref: textareaRef,
|
|
450
|
+
value: text,
|
|
451
|
+
rows: 1,
|
|
452
|
+
placeholder: "Message the agent",
|
|
453
|
+
"aria-label": "Message",
|
|
454
|
+
disabled,
|
|
455
|
+
className: cn(
|
|
456
|
+
"agents24-composer-textarea max-h-56 min-h-9 field-sizing-content resize-none overflow-y-auto border-0 bg-transparent px-2 shadow-none focus-visible:ring-0 dark:bg-transparent",
|
|
457
|
+
isExpanded ? "py-2" : "h-9 py-2"
|
|
458
|
+
),
|
|
459
|
+
onChange: (event) => {
|
|
460
|
+
draftRevisionRef.current += 1;
|
|
461
|
+
setText(event.target.value);
|
|
462
|
+
},
|
|
463
|
+
onKeyDown: (event) => {
|
|
464
|
+
if (event.key === "Enter" && !event.shiftKey && !event.nativeEvent.isComposing) {
|
|
465
|
+
event.preventDefault();
|
|
466
|
+
void submit();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
),
|
|
471
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "agents24-composer-actions flex items-center gap-1", children: [
|
|
472
|
+
utilityRow === "inline" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui.AgentChatContextStatus, { contextWindow }) : null,
|
|
473
|
+
utilityRow === "inline" ? modelSelector : null,
|
|
474
|
+
recordingAllowed ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
475
|
+
Button,
|
|
476
|
+
{
|
|
477
|
+
variant: recorder.isRecording ? "default" : "ghost",
|
|
478
|
+
size: "icon",
|
|
479
|
+
"aria-label": recorder.isRecording ? "Stop recording" : "Record audio",
|
|
480
|
+
disabled: disabled || isRunning,
|
|
481
|
+
onClick: () => {
|
|
482
|
+
if (recorder.isRecording) recorder.stop();
|
|
483
|
+
else void recorder.start();
|
|
484
|
+
},
|
|
485
|
+
children: recorder.isRecording ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Square, { className: "fill-current" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Mic, {})
|
|
486
|
+
}
|
|
487
|
+
) : null,
|
|
488
|
+
isRunning ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
489
|
+
Button,
|
|
490
|
+
{
|
|
491
|
+
size: "icon",
|
|
492
|
+
"aria-label": isCancelling ? "Cancelling response" : "Stop response",
|
|
493
|
+
disabled: disabled || isCancelling,
|
|
494
|
+
onClick: onStop,
|
|
495
|
+
children: isCancelling ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.LoaderCircle, { className: "animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.Square, { className: "fill-current" })
|
|
496
|
+
}
|
|
497
|
+
) : validationError ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Tooltip, { tabIndex: 0, children: [
|
|
498
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "icon", "aria-label": "Send message", disabled: true, onClick: () => void submit(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.ArrowUp, {}) }) }),
|
|
499
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TooltipContent, { children: validationError })
|
|
500
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Button, { size: "icon", "aria-label": "Send message", disabled, onClick: () => void submit(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react2.ArrowUp, {}) })
|
|
501
|
+
] })
|
|
502
|
+
]
|
|
503
|
+
}
|
|
504
|
+
),
|
|
505
|
+
showUtilityRow ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
506
|
+
"div",
|
|
507
|
+
{
|
|
508
|
+
"aria-hidden": !modelSelector && !hasContextWindow ? "true" : void 0,
|
|
509
|
+
className: "mt-2 flex min-h-8 items-center justify-between gap-2 px-1",
|
|
510
|
+
"data-agents24-chat-composer-utility": "",
|
|
511
|
+
children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "min-w-0", children: modelSelector }),
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_ui.AgentChatContextStatus, { contextWindow })
|
|
514
|
+
]
|
|
515
|
+
}
|
|
516
|
+
) : null
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// scaffold/src/components/chat/chat-message.tsx
|
|
523
|
+
var import_ui3 = require("@agents24/chat-react/ui");
|
|
524
|
+
|
|
525
|
+
// scaffold/src/components/chat/message-parts.tsx
|
|
526
|
+
var import_ui2 = require("@agents24/chat-react/ui");
|
|
527
|
+
|
|
528
|
+
// scaffold/src/components/chat/collapsible-user-message.tsx
|
|
529
|
+
var import_lucide_react3 = require("lucide-react");
|
|
530
|
+
var React3 = __toESM(require("react"), 1);
|
|
531
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
532
|
+
var collapseThreshold = 360;
|
|
533
|
+
function CollapsibleUserMessage({ content }) {
|
|
534
|
+
const [expanded, setExpanded] = React3.useState(false);
|
|
535
|
+
const contentId = React3.useId();
|
|
536
|
+
const collapsible = content.length > collapseThreshold;
|
|
537
|
+
const Icon = expanded ? import_lucide_react3.ChevronUp : import_lucide_react3.ChevronDown;
|
|
538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-w-0 flex-col gap-2", children: [
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
540
|
+
"div",
|
|
541
|
+
{
|
|
542
|
+
id: contentId,
|
|
543
|
+
className: `max-w-none min-w-0 text-[15px] leading-7 whitespace-pre-wrap wrap-break-word ${collapsible && !expanded ? "agents24-user-message-collapsed" : ""}`,
|
|
544
|
+
children: content
|
|
545
|
+
}
|
|
546
|
+
),
|
|
547
|
+
collapsible && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
548
|
+
Button,
|
|
549
|
+
{
|
|
550
|
+
variant: "ghost",
|
|
551
|
+
size: "sm",
|
|
552
|
+
type: "button",
|
|
553
|
+
"aria-controls": contentId,
|
|
554
|
+
"aria-expanded": expanded,
|
|
555
|
+
className: "h-auto w-fit px-0 py-0 text-muted-foreground hover:bg-transparent hover:text-foreground",
|
|
556
|
+
onClick: () => setExpanded((value) => !value),
|
|
557
|
+
children: [
|
|
558
|
+
expanded ? "Show less" : "Show more",
|
|
559
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, {})
|
|
560
|
+
]
|
|
561
|
+
}
|
|
562
|
+
)
|
|
563
|
+
] });
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
// scaffold/src/components/chat/external-link-dialog.tsx
|
|
567
|
+
var React4 = __toESM(require("react"), 1);
|
|
568
|
+
|
|
569
|
+
// scaffold/src/components/ui/dialog.tsx
|
|
570
|
+
var import_radix_ui4 = require("radix-ui");
|
|
571
|
+
var import_lucide_react4 = require("lucide-react");
|
|
572
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
573
|
+
function Dialog({
|
|
574
|
+
...props
|
|
575
|
+
}) {
|
|
576
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Dialog.Root, { "data-slot": "dialog", ...props });
|
|
577
|
+
}
|
|
578
|
+
function DialogPortal({
|
|
579
|
+
container,
|
|
580
|
+
...props
|
|
581
|
+
}) {
|
|
582
|
+
const themeContainer = useThemePortalContainer();
|
|
583
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Dialog.Portal, { container: container || themeContainer || void 0, "data-slot": "dialog-portal", ...props });
|
|
584
|
+
}
|
|
585
|
+
function DialogOverlay({
|
|
586
|
+
className,
|
|
587
|
+
...props
|
|
588
|
+
}) {
|
|
589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
590
|
+
import_radix_ui4.Dialog.Overlay,
|
|
591
|
+
{
|
|
592
|
+
"data-slot": "dialog-overlay",
|
|
593
|
+
className: cn(
|
|
594
|
+
"fixed inset-0 isolate z-50 bg-black/30 duration-100 supports-backdrop-filter:backdrop-blur-sm data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
595
|
+
className
|
|
596
|
+
),
|
|
597
|
+
...props
|
|
598
|
+
}
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
function DialogContent({
|
|
602
|
+
className,
|
|
603
|
+
children,
|
|
604
|
+
showCloseButton = true,
|
|
605
|
+
...props
|
|
606
|
+
}) {
|
|
607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DialogPortal, { children: [
|
|
608
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DialogOverlay, {}),
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
610
|
+
import_radix_ui4.Dialog.Content,
|
|
611
|
+
{
|
|
612
|
+
"data-slot": "dialog-content",
|
|
613
|
+
className: cn(
|
|
614
|
+
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-6 rounded-4xl bg-popover p-6 text-sm text-popover-foreground shadow-xl ring-1 ring-foreground/5 duration-100 outline-none sm:max-w-md dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
615
|
+
className
|
|
616
|
+
),
|
|
617
|
+
...props,
|
|
618
|
+
children: [
|
|
619
|
+
children,
|
|
620
|
+
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Dialog.Close, { "data-slot": "dialog-close", asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
621
|
+
Button,
|
|
622
|
+
{
|
|
623
|
+
variant: "ghost",
|
|
624
|
+
className: "absolute top-4 right-4 bg-secondary",
|
|
625
|
+
size: "icon-sm",
|
|
626
|
+
children: [
|
|
627
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
628
|
+
import_lucide_react4.XIcon,
|
|
629
|
+
{}
|
|
630
|
+
),
|
|
631
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "sr-only", children: "Close" })
|
|
632
|
+
]
|
|
633
|
+
}
|
|
634
|
+
) })
|
|
635
|
+
]
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
] });
|
|
639
|
+
}
|
|
640
|
+
function DialogHeader({ className, ...props }) {
|
|
641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
642
|
+
"div",
|
|
643
|
+
{
|
|
644
|
+
"data-slot": "dialog-header",
|
|
645
|
+
className: cn("flex flex-col gap-1.5", className),
|
|
646
|
+
...props
|
|
647
|
+
}
|
|
648
|
+
);
|
|
649
|
+
}
|
|
650
|
+
function DialogFooter({
|
|
651
|
+
className,
|
|
652
|
+
showCloseButton = false,
|
|
653
|
+
children,
|
|
654
|
+
...props
|
|
655
|
+
}) {
|
|
656
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
657
|
+
"div",
|
|
658
|
+
{
|
|
659
|
+
"data-slot": "dialog-footer",
|
|
660
|
+
className: cn(
|
|
661
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
662
|
+
className
|
|
663
|
+
),
|
|
664
|
+
...props,
|
|
665
|
+
children: [
|
|
666
|
+
children,
|
|
667
|
+
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_radix_ui4.Dialog.Close, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { variant: "outline", children: "Close" }) })
|
|
668
|
+
]
|
|
669
|
+
}
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
function DialogTitle({
|
|
673
|
+
className,
|
|
674
|
+
...props
|
|
675
|
+
}) {
|
|
676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
677
|
+
import_radix_ui4.Dialog.Title,
|
|
678
|
+
{
|
|
679
|
+
"data-slot": "dialog-title",
|
|
680
|
+
className: cn(
|
|
681
|
+
"font-heading text-base leading-none font-medium",
|
|
682
|
+
className
|
|
683
|
+
),
|
|
684
|
+
...props
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
}
|
|
688
|
+
function DialogDescription({
|
|
689
|
+
className,
|
|
690
|
+
...props
|
|
691
|
+
}) {
|
|
692
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
693
|
+
import_radix_ui4.Dialog.Description,
|
|
694
|
+
{
|
|
695
|
+
"data-slot": "dialog-description",
|
|
696
|
+
className: cn(
|
|
697
|
+
"text-sm text-muted-foreground *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
|
|
698
|
+
className
|
|
699
|
+
),
|
|
700
|
+
...props
|
|
701
|
+
}
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// scaffold/src/components/chat/external-link-dialog.tsx
|
|
706
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
707
|
+
function ExternalLinkDialog({ isOpen, onClose, onConfirm, url }) {
|
|
708
|
+
const [copied, setCopied] = React4.useState(false);
|
|
709
|
+
React4.useEffect(() => {
|
|
710
|
+
if (!isOpen) setCopied(false);
|
|
711
|
+
}, [isOpen]);
|
|
712
|
+
const copyUrl = async () => {
|
|
713
|
+
await navigator.clipboard.writeText(url);
|
|
714
|
+
setCopied(true);
|
|
715
|
+
};
|
|
716
|
+
const openUrl = () => {
|
|
717
|
+
onConfirm();
|
|
718
|
+
onClose();
|
|
719
|
+
};
|
|
720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Dialog, { open: isOpen, onOpenChange: (open) => {
|
|
721
|
+
if (!open) onClose();
|
|
722
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(DialogContent, { className: "max-h-[calc(100dvh-2rem)] min-w-0 overflow-hidden sm:max-w-md", children: [
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(DialogHeader, { children: [
|
|
724
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DialogTitle, { children: "Open external link?" }),
|
|
725
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(DialogDescription, { children: "You\u2019re about to visit an external website." })
|
|
726
|
+
] }),
|
|
727
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "max-h-32 overflow-auto rounded-md bg-muted p-3 font-mono text-xs wrap-break-word", children: url }),
|
|
728
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(DialogFooter, { children: [
|
|
729
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { variant: "outline", onClick: () => void copyUrl(), children: copied ? "Copied" : "Copy link" }),
|
|
730
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(Button, { onClick: openUrl, children: "Open link" })
|
|
731
|
+
] })
|
|
732
|
+
] }) });
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// scaffold/src/components/chat/message-parts.tsx
|
|
736
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
737
|
+
var linkSafety = {
|
|
738
|
+
enabled: true,
|
|
739
|
+
renderModal: (props) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ExternalLinkDialog, { ...props })
|
|
740
|
+
};
|
|
741
|
+
function ScaffoldTimeline(props) {
|
|
742
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
743
|
+
import_ui2.AgentResponseTimeline,
|
|
744
|
+
{
|
|
745
|
+
...props,
|
|
746
|
+
responseProps: {
|
|
747
|
+
className: "text-[15px] leading-7",
|
|
748
|
+
linkSafety
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
function MessageParts({
|
|
754
|
+
message,
|
|
755
|
+
getHitlActionState,
|
|
756
|
+
isLoading,
|
|
757
|
+
onHitlAction,
|
|
758
|
+
Timeline = ScaffoldTimeline
|
|
759
|
+
}) {
|
|
760
|
+
if (message.role === "assistant") {
|
|
761
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
762
|
+
Timeline,
|
|
763
|
+
{
|
|
764
|
+
getHitlActionState,
|
|
765
|
+
isLoading,
|
|
766
|
+
message,
|
|
767
|
+
onHitlAction: (part, response) => {
|
|
768
|
+
void onHitlAction(part, response).catch(() => void 0);
|
|
769
|
+
},
|
|
770
|
+
parts: message.parts
|
|
771
|
+
}
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
const text = message.parts.filter((part) => part.kind === "text").map((part) => part.kind === "text" ? part.text : "").join("") || message.content;
|
|
775
|
+
const supportingParts = message.parts.filter((part) => part.kind !== "text" && part.kind !== "data");
|
|
776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
777
|
+
supportingParts.map((part) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
778
|
+
import_ui2.AgentChatPart,
|
|
779
|
+
{
|
|
780
|
+
getHitlActionState,
|
|
781
|
+
message,
|
|
782
|
+
onHitlAction: (hitlPart, response) => {
|
|
783
|
+
void onHitlAction(hitlPart, response).catch(() => void 0);
|
|
784
|
+
},
|
|
785
|
+
part
|
|
786
|
+
},
|
|
787
|
+
part.id
|
|
788
|
+
)),
|
|
789
|
+
text ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(CollapsibleUserMessage, { content: text }) : null
|
|
790
|
+
] });
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// scaffold/src/components/ui/bubble.tsx
|
|
794
|
+
var import_class_variance_authority2 = require("class-variance-authority");
|
|
795
|
+
var import_radix_ui5 = require("radix-ui");
|
|
796
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
797
|
+
var bubbleVariants = (0, import_class_variance_authority2.cva)(
|
|
798
|
+
"group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full",
|
|
799
|
+
{
|
|
800
|
+
variants: {
|
|
801
|
+
variant: {
|
|
802
|
+
default: "*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80",
|
|
803
|
+
secondary: "*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]",
|
|
804
|
+
muted: "*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]",
|
|
805
|
+
tinted: "*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]",
|
|
806
|
+
outline: "*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30",
|
|
807
|
+
ghost: "border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50",
|
|
808
|
+
destructive: "*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30"
|
|
809
|
+
}
|
|
810
|
+
},
|
|
811
|
+
defaultVariants: {
|
|
812
|
+
variant: "default"
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
);
|
|
816
|
+
function Bubble({
|
|
817
|
+
variant = "default",
|
|
818
|
+
align = "start",
|
|
819
|
+
className,
|
|
820
|
+
...props
|
|
821
|
+
}) {
|
|
822
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
823
|
+
"div",
|
|
824
|
+
{
|
|
825
|
+
"data-slot": "bubble",
|
|
826
|
+
"data-variant": variant,
|
|
827
|
+
"data-align": align,
|
|
828
|
+
className: cn(bubbleVariants({ variant }), className),
|
|
829
|
+
...props
|
|
830
|
+
}
|
|
831
|
+
);
|
|
832
|
+
}
|
|
833
|
+
function BubbleContent({
|
|
834
|
+
asChild = false,
|
|
835
|
+
className,
|
|
836
|
+
...props
|
|
837
|
+
}) {
|
|
838
|
+
const Comp = asChild ? import_radix_ui5.Slot.Root : "div";
|
|
839
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
840
|
+
Comp,
|
|
841
|
+
{
|
|
842
|
+
"data-slot": "bubble-content",
|
|
843
|
+
className: cn(
|
|
844
|
+
"w-fit max-w-full min-w-0 overflow-hidden rounded-3xl border border-transparent px-3.5 py-2.5 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/30",
|
|
845
|
+
className
|
|
846
|
+
),
|
|
847
|
+
...props
|
|
848
|
+
}
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
var bubbleReactionsVariants = (0, import_class_variance_authority2.cva)(
|
|
852
|
+
"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0",
|
|
853
|
+
{
|
|
854
|
+
variants: {
|
|
855
|
+
side: {
|
|
856
|
+
top: "top-0 -translate-y-3/4",
|
|
857
|
+
bottom: "bottom-0 translate-y-3/4"
|
|
858
|
+
},
|
|
859
|
+
align: {
|
|
860
|
+
start: "left-3",
|
|
861
|
+
end: "right-3"
|
|
862
|
+
}
|
|
863
|
+
},
|
|
864
|
+
defaultVariants: {
|
|
865
|
+
side: "bottom",
|
|
866
|
+
align: "end"
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
);
|
|
870
|
+
|
|
871
|
+
// scaffold/src/components/ui/message.tsx
|
|
872
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
873
|
+
function Message({
|
|
874
|
+
className,
|
|
875
|
+
align = "start",
|
|
876
|
+
...props
|
|
877
|
+
}) {
|
|
878
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
879
|
+
"div",
|
|
880
|
+
{
|
|
881
|
+
"data-slot": "message",
|
|
882
|
+
"data-align": align,
|
|
883
|
+
className: cn(
|
|
884
|
+
"group/message relative flex w-full min-w-0 gap-2 text-sm data-[align=end]:flex-row-reverse",
|
|
885
|
+
className
|
|
886
|
+
),
|
|
887
|
+
...props
|
|
888
|
+
}
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
function MessageContent({ className, ...props }) {
|
|
892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
893
|
+
"div",
|
|
894
|
+
{
|
|
895
|
+
"data-slot": "message-content",
|
|
896
|
+
className: cn(
|
|
897
|
+
"flex w-full min-w-0 flex-col gap-2.5 wrap-break-word group-data-[align=end]/message:*:data-slot:self-end",
|
|
898
|
+
className
|
|
899
|
+
),
|
|
900
|
+
...props
|
|
901
|
+
}
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
function MessageFooter({ className, ...props }) {
|
|
905
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
906
|
+
"div",
|
|
907
|
+
{
|
|
908
|
+
"data-slot": "message-footer",
|
|
909
|
+
className: cn(
|
|
910
|
+
"flex max-w-full min-w-0 items-center px-3.5 text-xs font-medium text-muted-foreground group-has-data-[variant=ghost]/message:px-0 group-data-[align=end]/message:justify-end",
|
|
911
|
+
className
|
|
912
|
+
),
|
|
913
|
+
...props
|
|
914
|
+
}
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// scaffold/src/components/chat/chat-message.tsx
|
|
919
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
920
|
+
function ChatMessage({
|
|
921
|
+
allowFeedback,
|
|
922
|
+
getHitlActionState,
|
|
923
|
+
isLoading,
|
|
924
|
+
message,
|
|
925
|
+
onHitlAction,
|
|
926
|
+
onRegenerate,
|
|
927
|
+
onSetFeedback,
|
|
928
|
+
Timeline
|
|
929
|
+
}) {
|
|
930
|
+
const isUser = message.role === "user";
|
|
931
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(MessageContent, { children: [
|
|
932
|
+
isUser && message.attachments?.length ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_ui3.ChatAttachments, { className: "mb-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
933
|
+
import_ui3.ChatAttachment,
|
|
934
|
+
{
|
|
935
|
+
data: attachment
|
|
936
|
+
},
|
|
937
|
+
String(attachment.id || attachment.url || attachment.filename || index)
|
|
938
|
+
)) }) : null,
|
|
939
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Bubble, { variant: isUser ? "secondary" : "ghost", align: isUser ? "end" : "start", className: isUser ? "max-w-[min(75%,42rem)]" : "max-w-full overflow-visible", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(BubbleContent, { className: isUser ? "px-4 py-2.5" : "w-full overflow-visible", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
940
|
+
MessageParts,
|
|
941
|
+
{
|
|
942
|
+
getHitlActionState,
|
|
943
|
+
isLoading,
|
|
944
|
+
message,
|
|
945
|
+
onHitlAction,
|
|
946
|
+
Timeline
|
|
947
|
+
}
|
|
948
|
+
) }) }),
|
|
949
|
+
!isUser && message.isFinal !== false && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(MessageFooter, { className: "gap-1 opacity-70 transition-opacity group-hover/message:opacity-100", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
950
|
+
import_ui3.AgentChatDefaultActions,
|
|
951
|
+
{
|
|
952
|
+
handlers: {
|
|
953
|
+
feedback: message.feedback,
|
|
954
|
+
onCopy: (content) => {
|
|
955
|
+
void navigator.clipboard.writeText(content).catch(() => void 0);
|
|
956
|
+
},
|
|
957
|
+
onRetry: () => onRegenerate(),
|
|
958
|
+
onSetFeedback: allowFeedback ? (_message, input) => onSetFeedback(input) : void 0
|
|
959
|
+
},
|
|
960
|
+
message
|
|
961
|
+
}
|
|
962
|
+
) })
|
|
963
|
+
] }) });
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// scaffold/src/components/chat/theme-menu.tsx
|
|
967
|
+
var import_lucide_react5 = require("lucide-react");
|
|
968
|
+
var React5 = __toESM(require("react"), 1);
|
|
969
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
970
|
+
var options = [
|
|
971
|
+
{ value: "system", label: "System", icon: import_lucide_react5.Laptop },
|
|
972
|
+
{ value: "light", label: "Light", icon: import_lucide_react5.Sun },
|
|
973
|
+
{ value: "dark", label: "Dark", icon: import_lucide_react5.Moon }
|
|
974
|
+
];
|
|
975
|
+
function ThemeMenu() {
|
|
976
|
+
const { appearance, setAppearance } = useTheme();
|
|
977
|
+
const [open, setOpen] = React5.useState(false);
|
|
978
|
+
const rootRef = React5.useRef(null);
|
|
979
|
+
const firstItemRef = React5.useRef(null);
|
|
980
|
+
const menuId = React5.useId();
|
|
981
|
+
const ActiveIcon = options.find((item) => item.value === appearance)?.icon ?? import_lucide_react5.Laptop;
|
|
982
|
+
React5.useEffect(() => {
|
|
983
|
+
if (!open) return;
|
|
984
|
+
firstItemRef.current?.focus();
|
|
985
|
+
const closeOnOutsidePointer = (event) => {
|
|
986
|
+
if (!rootRef.current?.contains(event.target)) setOpen(false);
|
|
987
|
+
};
|
|
988
|
+
const closeOnEscape = (event) => {
|
|
989
|
+
if (event.key === "Escape") setOpen(false);
|
|
990
|
+
};
|
|
991
|
+
document.addEventListener("pointerdown", closeOnOutsidePointer);
|
|
992
|
+
document.addEventListener("keydown", closeOnEscape);
|
|
993
|
+
return () => {
|
|
994
|
+
document.removeEventListener("pointerdown", closeOnOutsidePointer);
|
|
995
|
+
document.removeEventListener("keydown", closeOnEscape);
|
|
996
|
+
};
|
|
997
|
+
}, [open]);
|
|
998
|
+
const label = appearance === "system" ? "System" : appearance === "light" ? "Light" : "Dark";
|
|
999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { ref: rootRef, className: "relative", children: [
|
|
1000
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1001
|
+
Button,
|
|
1002
|
+
{
|
|
1003
|
+
"aria-controls": menuId,
|
|
1004
|
+
"aria-expanded": open,
|
|
1005
|
+
"aria-haspopup": "menu",
|
|
1006
|
+
"aria-label": `Appearance: ${label}`,
|
|
1007
|
+
onClick: () => setOpen((value) => !value),
|
|
1008
|
+
size: "icon-sm",
|
|
1009
|
+
variant: "ghost",
|
|
1010
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(ActiveIcon, {})
|
|
1011
|
+
}
|
|
1012
|
+
),
|
|
1013
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1014
|
+
"div",
|
|
1015
|
+
{
|
|
1016
|
+
id: menuId,
|
|
1017
|
+
className: "absolute end-0 top-full z-50 mt-1 flex min-w-44 flex-col rounded-xl border bg-popover p-1 text-popover-foreground shadow-md",
|
|
1018
|
+
role: "menu",
|
|
1019
|
+
children: options.map(({ value, label: optionLabel, icon: Icon }, index) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1020
|
+
Button,
|
|
1021
|
+
{
|
|
1022
|
+
ref: index === 0 ? firstItemRef : void 0,
|
|
1023
|
+
"aria-current": appearance === value ? "true" : void 0,
|
|
1024
|
+
className: "w-full justify-start",
|
|
1025
|
+
onClick: () => {
|
|
1026
|
+
setAppearance(value);
|
|
1027
|
+
setOpen(false);
|
|
1028
|
+
},
|
|
1029
|
+
role: "menuitem",
|
|
1030
|
+
size: "sm",
|
|
1031
|
+
variant: "ghost",
|
|
1032
|
+
children: [
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Icon, {}),
|
|
1034
|
+
" ",
|
|
1035
|
+
optionLabel
|
|
1036
|
+
]
|
|
1037
|
+
},
|
|
1038
|
+
value
|
|
1039
|
+
))
|
|
1040
|
+
}
|
|
1041
|
+
) : null
|
|
1042
|
+
] });
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
// scaffold/src/components/chat/thread-sidebar.tsx
|
|
1046
|
+
var import_react = require("@agents24/react");
|
|
1047
|
+
var import_lucide_react10 = require("lucide-react");
|
|
1048
|
+
|
|
1049
|
+
// scaffold/src/components/chat/identity-control.tsx
|
|
1050
|
+
var import_lucide_react9 = require("lucide-react");
|
|
1051
|
+
|
|
1052
|
+
// scaffold/src/components/ui/dropdown-menu.tsx
|
|
1053
|
+
var import_radix_ui6 = require("radix-ui");
|
|
1054
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1055
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1056
|
+
function DropdownMenu({
|
|
1057
|
+
...props
|
|
1058
|
+
}) {
|
|
1059
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_radix_ui6.DropdownMenu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
1060
|
+
}
|
|
1061
|
+
function DropdownMenuTrigger({
|
|
1062
|
+
...props
|
|
1063
|
+
}) {
|
|
1064
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1065
|
+
import_radix_ui6.DropdownMenu.Trigger,
|
|
1066
|
+
{
|
|
1067
|
+
"data-slot": "dropdown-menu-trigger",
|
|
1068
|
+
...props
|
|
1069
|
+
}
|
|
1070
|
+
);
|
|
1071
|
+
}
|
|
1072
|
+
function DropdownMenuContent({
|
|
1073
|
+
className,
|
|
1074
|
+
align = "start",
|
|
1075
|
+
sideOffset = 4,
|
|
1076
|
+
...props
|
|
1077
|
+
}) {
|
|
1078
|
+
const themeContainer = useThemePortalContainer();
|
|
1079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_radix_ui6.DropdownMenu.Portal, { container: themeContainer || void 0, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1080
|
+
import_radix_ui6.DropdownMenu.Content,
|
|
1081
|
+
{
|
|
1082
|
+
"data-slot": "dropdown-menu-content",
|
|
1083
|
+
sideOffset,
|
|
1084
|
+
align,
|
|
1085
|
+
className: cn("z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-48 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-3xl bg-popover p-1.5 text-popover-foreground shadow-lg ring-1 ring-foreground/5 duration-100 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 data-[state=closed]:overflow-hidden dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className),
|
|
1086
|
+
...props
|
|
1087
|
+
}
|
|
1088
|
+
) });
|
|
1089
|
+
}
|
|
1090
|
+
function DropdownMenuItem({
|
|
1091
|
+
className,
|
|
1092
|
+
inset,
|
|
1093
|
+
variant = "default",
|
|
1094
|
+
...props
|
|
1095
|
+
}) {
|
|
1096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1097
|
+
import_radix_ui6.DropdownMenu.Item,
|
|
1098
|
+
{
|
|
1099
|
+
"data-slot": "dropdown-menu-item",
|
|
1100
|
+
"data-inset": inset,
|
|
1101
|
+
"data-variant": variant,
|
|
1102
|
+
className: cn(
|
|
1103
|
+
"group/dropdown-menu-item relative flex cursor-default items-center gap-2.5 rounded-2xl px-3 py-2 text-sm font-medium outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-9.5 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
|
|
1104
|
+
className
|
|
1105
|
+
),
|
|
1106
|
+
...props
|
|
1107
|
+
}
|
|
1108
|
+
);
|
|
1109
|
+
}
|
|
1110
|
+
function DropdownMenuLabel({
|
|
1111
|
+
className,
|
|
1112
|
+
inset,
|
|
1113
|
+
...props
|
|
1114
|
+
}) {
|
|
1115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1116
|
+
import_radix_ui6.DropdownMenu.Label,
|
|
1117
|
+
{
|
|
1118
|
+
"data-slot": "dropdown-menu-label",
|
|
1119
|
+
"data-inset": inset,
|
|
1120
|
+
className: cn(
|
|
1121
|
+
"px-3 py-2.5 text-xs text-muted-foreground data-inset:pl-9.5",
|
|
1122
|
+
className
|
|
1123
|
+
),
|
|
1124
|
+
...props
|
|
1125
|
+
}
|
|
1126
|
+
);
|
|
1127
|
+
}
|
|
1128
|
+
function DropdownMenuSeparator({
|
|
1129
|
+
className,
|
|
1130
|
+
...props
|
|
1131
|
+
}) {
|
|
1132
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
1133
|
+
import_radix_ui6.DropdownMenu.Separator,
|
|
1134
|
+
{
|
|
1135
|
+
"data-slot": "dropdown-menu-separator",
|
|
1136
|
+
className: cn("-mx-1.5 my-1.5 h-px bg-border/50", className),
|
|
1137
|
+
...props
|
|
1138
|
+
}
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
// scaffold/src/components/ui/sidebar.tsx
|
|
1143
|
+
var React7 = __toESM(require("react"), 1);
|
|
1144
|
+
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1145
|
+
var import_radix_ui9 = require("radix-ui");
|
|
1146
|
+
|
|
1147
|
+
// scaffold/src/hooks/use-mobile.ts
|
|
1148
|
+
var React6 = __toESM(require("react"), 1);
|
|
1149
|
+
var MOBILE_BREAKPOINT = 768;
|
|
1150
|
+
function useIsMobile() {
|
|
1151
|
+
const [isMobile, setIsMobile] = React6.useState(void 0);
|
|
1152
|
+
React6.useEffect(() => {
|
|
1153
|
+
const onChange = () => {
|
|
1154
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
|
1155
|
+
};
|
|
1156
|
+
if (typeof window.matchMedia !== "function") {
|
|
1157
|
+
onChange();
|
|
1158
|
+
window.addEventListener("resize", onChange);
|
|
1159
|
+
return () => window.removeEventListener("resize", onChange);
|
|
1160
|
+
}
|
|
1161
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
|
1162
|
+
mql.addEventListener("change", onChange);
|
|
1163
|
+
onChange();
|
|
1164
|
+
return () => mql.removeEventListener("change", onChange);
|
|
1165
|
+
}, []);
|
|
1166
|
+
return !!isMobile;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
// scaffold/src/components/ui/input.tsx
|
|
1170
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1171
|
+
|
|
1172
|
+
// scaffold/src/components/ui/separator.tsx
|
|
1173
|
+
var import_radix_ui7 = require("radix-ui");
|
|
1174
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1175
|
+
|
|
1176
|
+
// scaffold/src/components/ui/sheet.tsx
|
|
1177
|
+
var import_radix_ui8 = require("radix-ui");
|
|
1178
|
+
var import_lucide_react7 = require("lucide-react");
|
|
1179
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1180
|
+
function Sheet({ ...props }) {
|
|
1181
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_radix_ui8.Dialog.Root, { "data-slot": "sheet", ...props });
|
|
1182
|
+
}
|
|
1183
|
+
function SheetPortal({
|
|
1184
|
+
container,
|
|
1185
|
+
...props
|
|
1186
|
+
}) {
|
|
1187
|
+
const themeContainer = useThemePortalContainer();
|
|
1188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_radix_ui8.Dialog.Portal, { container: container || themeContainer || void 0, "data-slot": "sheet-portal", ...props });
|
|
1189
|
+
}
|
|
1190
|
+
function SheetOverlay({
|
|
1191
|
+
className,
|
|
1192
|
+
...props
|
|
1193
|
+
}) {
|
|
1194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1195
|
+
import_radix_ui8.Dialog.Overlay,
|
|
1196
|
+
{
|
|
1197
|
+
"data-slot": "sheet-overlay",
|
|
1198
|
+
className: cn(
|
|
1199
|
+
"fixed inset-0 z-50 bg-black/30 duration-100 supports-backdrop-filter:backdrop-blur-sm data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0",
|
|
1200
|
+
className
|
|
1201
|
+
),
|
|
1202
|
+
...props
|
|
1203
|
+
}
|
|
1204
|
+
);
|
|
1205
|
+
}
|
|
1206
|
+
function SheetContent({
|
|
1207
|
+
className,
|
|
1208
|
+
children,
|
|
1209
|
+
side = "right",
|
|
1210
|
+
showCloseButton = true,
|
|
1211
|
+
...props
|
|
1212
|
+
}) {
|
|
1213
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(SheetPortal, { children: [
|
|
1214
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(SheetOverlay, {}),
|
|
1215
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
1216
|
+
import_radix_ui8.Dialog.Content,
|
|
1217
|
+
{
|
|
1218
|
+
"data-slot": "sheet-content",
|
|
1219
|
+
"data-side": side,
|
|
1220
|
+
className: cn(
|
|
1221
|
+
"fixed z-50 flex flex-col bg-popover bg-clip-padding text-sm text-popover-foreground shadow-xl transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-[side=bottom]:data-open:slide-in-from-bottom-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:animate-out data-closed:fade-out-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=right]:data-closed:slide-out-to-right-10 data-[side=top]:data-closed:slide-out-to-top-10",
|
|
1222
|
+
className
|
|
1223
|
+
),
|
|
1224
|
+
...props,
|
|
1225
|
+
children: [
|
|
1226
|
+
children,
|
|
1227
|
+
showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_radix_ui8.Dialog.Close, { "data-slot": "sheet-close", asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
1228
|
+
Button,
|
|
1229
|
+
{
|
|
1230
|
+
variant: "ghost",
|
|
1231
|
+
className: "absolute top-4 right-4 bg-secondary",
|
|
1232
|
+
size: "icon-sm",
|
|
1233
|
+
children: [
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1235
|
+
import_lucide_react7.XIcon,
|
|
1236
|
+
{}
|
|
1237
|
+
),
|
|
1238
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "sr-only", children: "Close" })
|
|
1239
|
+
]
|
|
1240
|
+
}
|
|
1241
|
+
) })
|
|
1242
|
+
]
|
|
1243
|
+
}
|
|
1244
|
+
)
|
|
1245
|
+
] });
|
|
1246
|
+
}
|
|
1247
|
+
function SheetHeader({ className, ...props }) {
|
|
1248
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1249
|
+
"div",
|
|
1250
|
+
{
|
|
1251
|
+
"data-slot": "sheet-header",
|
|
1252
|
+
className: cn("flex flex-col gap-1.5 p-6", className),
|
|
1253
|
+
...props
|
|
1254
|
+
}
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
function SheetTitle({
|
|
1258
|
+
className,
|
|
1259
|
+
...props
|
|
1260
|
+
}) {
|
|
1261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1262
|
+
import_radix_ui8.Dialog.Title,
|
|
1263
|
+
{
|
|
1264
|
+
"data-slot": "sheet-title",
|
|
1265
|
+
className: cn(
|
|
1266
|
+
"font-heading text-base font-medium text-foreground",
|
|
1267
|
+
className
|
|
1268
|
+
),
|
|
1269
|
+
...props
|
|
1270
|
+
}
|
|
1271
|
+
);
|
|
1272
|
+
}
|
|
1273
|
+
function SheetDescription({
|
|
1274
|
+
className,
|
|
1275
|
+
...props
|
|
1276
|
+
}) {
|
|
1277
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
1278
|
+
import_radix_ui8.Dialog.Description,
|
|
1279
|
+
{
|
|
1280
|
+
"data-slot": "sheet-description",
|
|
1281
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
1282
|
+
...props
|
|
1283
|
+
}
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
// scaffold/src/components/ui/skeleton.tsx
|
|
1288
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1289
|
+
|
|
1290
|
+
// scaffold/src/components/ui/sidebar.tsx
|
|
1291
|
+
var import_lucide_react8 = require("lucide-react");
|
|
1292
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1293
|
+
var SIDEBAR_COOKIE_NAME = "sidebar_state";
|
|
1294
|
+
var SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
1295
|
+
var SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
1296
|
+
var SidebarContext = React7.createContext(null);
|
|
1297
|
+
function useSidebar() {
|
|
1298
|
+
const context = React7.useContext(SidebarContext);
|
|
1299
|
+
if (!context) {
|
|
1300
|
+
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
1301
|
+
}
|
|
1302
|
+
return context;
|
|
1303
|
+
}
|
|
1304
|
+
function SidebarProvider({
|
|
1305
|
+
defaultOpen = true,
|
|
1306
|
+
open: openProp,
|
|
1307
|
+
onOpenChange: setOpenProp,
|
|
1308
|
+
className,
|
|
1309
|
+
children,
|
|
1310
|
+
...props
|
|
1311
|
+
}) {
|
|
1312
|
+
const isMobile = useIsMobile();
|
|
1313
|
+
const [openMobile, setOpenMobile] = React7.useState(false);
|
|
1314
|
+
const [_open, _setOpen] = React7.useState(defaultOpen);
|
|
1315
|
+
const open = openProp ?? _open;
|
|
1316
|
+
const setOpen = React7.useCallback(
|
|
1317
|
+
(value) => {
|
|
1318
|
+
const openState = typeof value === "function" ? value(open) : value;
|
|
1319
|
+
if (setOpenProp) {
|
|
1320
|
+
setOpenProp(openState);
|
|
1321
|
+
} else {
|
|
1322
|
+
_setOpen(openState);
|
|
1323
|
+
}
|
|
1324
|
+
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
1325
|
+
},
|
|
1326
|
+
[setOpenProp, open]
|
|
1327
|
+
);
|
|
1328
|
+
const toggleSidebar = React7.useCallback(() => {
|
|
1329
|
+
return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
|
|
1330
|
+
}, [isMobile, setOpen, setOpenMobile]);
|
|
1331
|
+
React7.useEffect(() => {
|
|
1332
|
+
const handleKeyDown = (event) => {
|
|
1333
|
+
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
1334
|
+
event.preventDefault();
|
|
1335
|
+
toggleSidebar();
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
1339
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1340
|
+
}, [toggleSidebar]);
|
|
1341
|
+
const state = open ? "expanded" : "collapsed";
|
|
1342
|
+
const contextValue = React7.useMemo(
|
|
1343
|
+
() => ({
|
|
1344
|
+
state,
|
|
1345
|
+
open,
|
|
1346
|
+
setOpen,
|
|
1347
|
+
isMobile,
|
|
1348
|
+
openMobile,
|
|
1349
|
+
setOpenMobile,
|
|
1350
|
+
toggleSidebar
|
|
1351
|
+
}),
|
|
1352
|
+
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
|
|
1353
|
+
);
|
|
1354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1355
|
+
"div",
|
|
1356
|
+
{
|
|
1357
|
+
"data-slot": "sidebar-wrapper",
|
|
1358
|
+
className: cn(
|
|
1359
|
+
"group/sidebar-wrapper flex min-h-svh w-full [--sidebar-width:16rem] [--sidebar-width-icon:3rem] has-data-[variant=inset]:bg-sidebar",
|
|
1360
|
+
className
|
|
1361
|
+
),
|
|
1362
|
+
...props,
|
|
1363
|
+
children
|
|
1364
|
+
}
|
|
1365
|
+
) });
|
|
1366
|
+
}
|
|
1367
|
+
function Sidebar({
|
|
1368
|
+
side = "left",
|
|
1369
|
+
variant = "sidebar",
|
|
1370
|
+
collapsible = "offcanvas",
|
|
1371
|
+
className,
|
|
1372
|
+
children,
|
|
1373
|
+
dir,
|
|
1374
|
+
...props
|
|
1375
|
+
}) {
|
|
1376
|
+
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
|
1377
|
+
if (collapsible === "none") {
|
|
1378
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1379
|
+
"div",
|
|
1380
|
+
{
|
|
1381
|
+
"data-slot": "sidebar",
|
|
1382
|
+
className: cn(
|
|
1383
|
+
"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground",
|
|
1384
|
+
className
|
|
1385
|
+
),
|
|
1386
|
+
...props,
|
|
1387
|
+
children
|
|
1388
|
+
}
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1391
|
+
if (isMobile) {
|
|
1392
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Sheet, { open: openMobile, onOpenChange: setOpenMobile, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1393
|
+
SheetContent,
|
|
1394
|
+
{
|
|
1395
|
+
dir,
|
|
1396
|
+
"data-sidebar": "sidebar",
|
|
1397
|
+
"data-slot": "sidebar",
|
|
1398
|
+
"data-mobile": "true",
|
|
1399
|
+
className: "w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [--sidebar-width:18rem] [&>button]:hidden",
|
|
1400
|
+
side,
|
|
1401
|
+
children: [
|
|
1402
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(SheetHeader, { className: "sr-only", children: [
|
|
1403
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SheetTitle, { children: "Sidebar" }),
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SheetDescription, { children: "Displays the mobile sidebar." })
|
|
1405
|
+
] }),
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex h-full w-full flex-col", children })
|
|
1407
|
+
]
|
|
1408
|
+
}
|
|
1409
|
+
) });
|
|
1410
|
+
}
|
|
1411
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1412
|
+
"div",
|
|
1413
|
+
{
|
|
1414
|
+
className: "group peer hidden text-sidebar-foreground md:block",
|
|
1415
|
+
"data-state": state,
|
|
1416
|
+
"data-collapsible": state === "collapsed" ? collapsible : "",
|
|
1417
|
+
"data-variant": variant,
|
|
1418
|
+
"data-side": side,
|
|
1419
|
+
"data-slot": "sidebar",
|
|
1420
|
+
children: [
|
|
1421
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1422
|
+
"div",
|
|
1423
|
+
{
|
|
1424
|
+
"data-slot": "sidebar-gap",
|
|
1425
|
+
className: cn(
|
|
1426
|
+
"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear",
|
|
1427
|
+
"group-data-[collapsible=offcanvas]:w-0",
|
|
1428
|
+
"group-data-[side=right]:rotate-180",
|
|
1429
|
+
variant === "floating" || variant === "inset" ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)"
|
|
1430
|
+
)
|
|
1431
|
+
}
|
|
1432
|
+
),
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1434
|
+
"div",
|
|
1435
|
+
{
|
|
1436
|
+
"data-slot": "sidebar-container",
|
|
1437
|
+
"data-side": side,
|
|
1438
|
+
className: cn(
|
|
1439
|
+
"fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear data-[side=left]:left-0 data-[side=left]:group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)] data-[side=right]:right-0 data-[side=right]:group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)] md:flex",
|
|
1440
|
+
// Adjust the padding for floating and inset variants.
|
|
1441
|
+
variant === "floating" || variant === "inset" ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
|
1442
|
+
className
|
|
1443
|
+
),
|
|
1444
|
+
...props,
|
|
1445
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1446
|
+
"div",
|
|
1447
|
+
{
|
|
1448
|
+
"data-sidebar": "sidebar",
|
|
1449
|
+
"data-slot": "sidebar-inner",
|
|
1450
|
+
className: "flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-2xl group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border",
|
|
1451
|
+
children
|
|
1452
|
+
}
|
|
1453
|
+
)
|
|
1454
|
+
}
|
|
1455
|
+
)
|
|
1456
|
+
]
|
|
1457
|
+
}
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1460
|
+
function SidebarTrigger({
|
|
1461
|
+
className,
|
|
1462
|
+
onClick,
|
|
1463
|
+
...props
|
|
1464
|
+
}) {
|
|
1465
|
+
const { toggleSidebar } = useSidebar();
|
|
1466
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1467
|
+
Button,
|
|
1468
|
+
{
|
|
1469
|
+
"data-sidebar": "trigger",
|
|
1470
|
+
"data-slot": "sidebar-trigger",
|
|
1471
|
+
variant: "ghost",
|
|
1472
|
+
size: "icon-sm",
|
|
1473
|
+
className: cn(className),
|
|
1474
|
+
onClick: (event) => {
|
|
1475
|
+
onClick?.(event);
|
|
1476
|
+
toggleSidebar();
|
|
1477
|
+
},
|
|
1478
|
+
...props,
|
|
1479
|
+
children: [
|
|
1480
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react8.PanelLeftIcon, {}),
|
|
1481
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "sr-only", children: "Toggle Sidebar" })
|
|
1482
|
+
]
|
|
1483
|
+
}
|
|
1484
|
+
);
|
|
1485
|
+
}
|
|
1486
|
+
function SidebarRail({ className, ...props }) {
|
|
1487
|
+
const { toggleSidebar } = useSidebar();
|
|
1488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1489
|
+
"button",
|
|
1490
|
+
{
|
|
1491
|
+
"data-sidebar": "rail",
|
|
1492
|
+
"data-slot": "sidebar-rail",
|
|
1493
|
+
"aria-label": "Toggle Sidebar",
|
|
1494
|
+
tabIndex: -1,
|
|
1495
|
+
onClick: toggleSidebar,
|
|
1496
|
+
title: "Toggle Sidebar",
|
|
1497
|
+
className: cn(
|
|
1498
|
+
"absolute inset-y-0 z-20 hidden w-4 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:start-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex ltr:-translate-x-1/2 rtl:-translate-x-1/2",
|
|
1499
|
+
"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize",
|
|
1500
|
+
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
|
1501
|
+
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar",
|
|
1502
|
+
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
|
1503
|
+
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
|
1504
|
+
className
|
|
1505
|
+
),
|
|
1506
|
+
...props
|
|
1507
|
+
}
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
function SidebarInset({ className, ...props }) {
|
|
1511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1512
|
+
"main",
|
|
1513
|
+
{
|
|
1514
|
+
"data-slot": "sidebar-inset",
|
|
1515
|
+
className: cn(
|
|
1516
|
+
"relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-2xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2",
|
|
1517
|
+
className
|
|
1518
|
+
),
|
|
1519
|
+
...props
|
|
1520
|
+
}
|
|
1521
|
+
);
|
|
1522
|
+
}
|
|
1523
|
+
function SidebarHeader({ className, ...props }) {
|
|
1524
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1525
|
+
"div",
|
|
1526
|
+
{
|
|
1527
|
+
"data-slot": "sidebar-header",
|
|
1528
|
+
"data-sidebar": "header",
|
|
1529
|
+
className: cn(
|
|
1530
|
+
"flex flex-col gap-2 p-2 [--radius:var(--radius-xl)]",
|
|
1531
|
+
className
|
|
1532
|
+
),
|
|
1533
|
+
...props
|
|
1534
|
+
}
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
function SidebarFooter({ className, ...props }) {
|
|
1538
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1539
|
+
"div",
|
|
1540
|
+
{
|
|
1541
|
+
"data-slot": "sidebar-footer",
|
|
1542
|
+
"data-sidebar": "footer",
|
|
1543
|
+
className: cn("flex flex-col gap-2 p-2", className),
|
|
1544
|
+
...props
|
|
1545
|
+
}
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
function SidebarContent({ className, ...props }) {
|
|
1549
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1550
|
+
"div",
|
|
1551
|
+
{
|
|
1552
|
+
"data-slot": "sidebar-content",
|
|
1553
|
+
"data-sidebar": "content",
|
|
1554
|
+
className: cn(
|
|
1555
|
+
"no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-auto [--radius:var(--radius-xl)] group-data-[collapsible=icon]:overflow-hidden",
|
|
1556
|
+
className
|
|
1557
|
+
),
|
|
1558
|
+
...props
|
|
1559
|
+
}
|
|
1560
|
+
);
|
|
1561
|
+
}
|
|
1562
|
+
function SidebarGroup({ className, ...props }) {
|
|
1563
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1564
|
+
"div",
|
|
1565
|
+
{
|
|
1566
|
+
"data-slot": "sidebar-group",
|
|
1567
|
+
"data-sidebar": "group",
|
|
1568
|
+
className: cn("relative flex w-full min-w-0 flex-col p-2", className),
|
|
1569
|
+
...props
|
|
1570
|
+
}
|
|
1571
|
+
);
|
|
1572
|
+
}
|
|
1573
|
+
function SidebarGroupContent({
|
|
1574
|
+
className,
|
|
1575
|
+
...props
|
|
1576
|
+
}) {
|
|
1577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1578
|
+
"div",
|
|
1579
|
+
{
|
|
1580
|
+
"data-slot": "sidebar-group-content",
|
|
1581
|
+
"data-sidebar": "group-content",
|
|
1582
|
+
className: cn("w-full text-sm", className),
|
|
1583
|
+
...props
|
|
1584
|
+
}
|
|
1585
|
+
);
|
|
1586
|
+
}
|
|
1587
|
+
function SidebarMenu({ className, ...props }) {
|
|
1588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1589
|
+
"ul",
|
|
1590
|
+
{
|
|
1591
|
+
"data-slot": "sidebar-menu",
|
|
1592
|
+
"data-sidebar": "menu",
|
|
1593
|
+
className: cn("flex w-full min-w-0 flex-col gap-0.5", className),
|
|
1594
|
+
...props
|
|
1595
|
+
}
|
|
1596
|
+
);
|
|
1597
|
+
}
|
|
1598
|
+
function SidebarMenuItem({ className, ...props }) {
|
|
1599
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1600
|
+
"li",
|
|
1601
|
+
{
|
|
1602
|
+
"data-slot": "sidebar-menu-item",
|
|
1603
|
+
"data-sidebar": "menu-item",
|
|
1604
|
+
className: cn("group/menu-item relative", className),
|
|
1605
|
+
...props
|
|
1606
|
+
}
|
|
1607
|
+
);
|
|
1608
|
+
}
|
|
1609
|
+
var sidebarMenuButtonVariants = (0, import_class_variance_authority3.cva)(
|
|
1610
|
+
"peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-xl px-3 py-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate",
|
|
1611
|
+
{
|
|
1612
|
+
variants: {
|
|
1613
|
+
variant: {
|
|
1614
|
+
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
1615
|
+
outline: "bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]"
|
|
1616
|
+
},
|
|
1617
|
+
size: {
|
|
1618
|
+
default: "h-9 text-sm",
|
|
1619
|
+
sm: "h-8 text-xs",
|
|
1620
|
+
lg: "h-14 px-3 text-sm group-data-[collapsible=icon]:p-0!"
|
|
1621
|
+
}
|
|
1622
|
+
},
|
|
1623
|
+
defaultVariants: {
|
|
1624
|
+
variant: "default",
|
|
1625
|
+
size: "default"
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
);
|
|
1629
|
+
function SidebarMenuButton({
|
|
1630
|
+
asChild = false,
|
|
1631
|
+
isActive = false,
|
|
1632
|
+
variant = "default",
|
|
1633
|
+
size = "default",
|
|
1634
|
+
tooltip,
|
|
1635
|
+
className,
|
|
1636
|
+
...props
|
|
1637
|
+
}) {
|
|
1638
|
+
const Comp = asChild ? import_radix_ui9.Slot.Root : "button";
|
|
1639
|
+
const { isMobile, state } = useSidebar();
|
|
1640
|
+
const button = /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1641
|
+
Comp,
|
|
1642
|
+
{
|
|
1643
|
+
"data-slot": "sidebar-menu-button",
|
|
1644
|
+
"data-sidebar": "menu-button",
|
|
1645
|
+
"data-size": size,
|
|
1646
|
+
"data-active": isActive,
|
|
1647
|
+
className: cn(sidebarMenuButtonVariants({ variant, size }), className),
|
|
1648
|
+
...props
|
|
1649
|
+
}
|
|
1650
|
+
);
|
|
1651
|
+
if (!tooltip) {
|
|
1652
|
+
return button;
|
|
1653
|
+
}
|
|
1654
|
+
if (typeof tooltip === "string") {
|
|
1655
|
+
tooltip = {
|
|
1656
|
+
children: tooltip
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Tooltip, { children: [
|
|
1660
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(TooltipTrigger, { asChild: true, children: button }),
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1662
|
+
TooltipContent,
|
|
1663
|
+
{
|
|
1664
|
+
side: "right",
|
|
1665
|
+
align: "center",
|
|
1666
|
+
hidden: state !== "collapsed" || isMobile,
|
|
1667
|
+
...tooltip
|
|
1668
|
+
}
|
|
1669
|
+
)
|
|
1670
|
+
] });
|
|
1671
|
+
}
|
|
1672
|
+
function SidebarMenuAction({
|
|
1673
|
+
className,
|
|
1674
|
+
asChild = false,
|
|
1675
|
+
showOnHover = false,
|
|
1676
|
+
...props
|
|
1677
|
+
}) {
|
|
1678
|
+
const Comp = asChild ? import_radix_ui9.Slot.Root : "button";
|
|
1679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1680
|
+
Comp,
|
|
1681
|
+
{
|
|
1682
|
+
"data-slot": "sidebar-menu-action",
|
|
1683
|
+
"data-sidebar": "menu-action",
|
|
1684
|
+
className: cn(
|
|
1685
|
+
"absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-xl p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-2 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0",
|
|
1686
|
+
showOnHover && "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground aria-expanded:opacity-100 md:opacity-0",
|
|
1687
|
+
className
|
|
1688
|
+
),
|
|
1689
|
+
...props
|
|
1690
|
+
}
|
|
1691
|
+
);
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
// scaffold/src/components/chat/identity-control.tsx
|
|
1695
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1696
|
+
function identityLabel(identity) {
|
|
1697
|
+
if (identity.displayName) return identity.displayName;
|
|
1698
|
+
if (identity.state === "authenticated") return "Signed in";
|
|
1699
|
+
if (identity.state === "loading") return "Loading identity";
|
|
1700
|
+
if (identity.state === "error") return "Identity unavailable";
|
|
1701
|
+
if (identity.state === "signed_out") return "Sign in";
|
|
1702
|
+
return "Guest";
|
|
1703
|
+
}
|
|
1704
|
+
function IdentityAvatar({ identity }) {
|
|
1705
|
+
const label = identityLabel(identity);
|
|
1706
|
+
if (identity.avatarUrl) {
|
|
1707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("img", { alt: "", className: "size-6 rounded-full object-cover", src: identity.avatarUrl });
|
|
1708
|
+
}
|
|
1709
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "flex size-6 items-center justify-center rounded-full bg-sidebar-accent text-[10px] font-semibold", "aria-hidden": "true", children: identity.displayName ? identity.displayName.slice(0, 1).toUpperCase() : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.UserRound, { className: "size-3.5" }) });
|
|
1710
|
+
}
|
|
1711
|
+
function IdentityControl({ identity }) {
|
|
1712
|
+
const label = identityLabel(identity);
|
|
1713
|
+
const canSignOut = identity.state === "authenticated" && Boolean(identity.onSignOut);
|
|
1714
|
+
const canSignIn = (identity.state === "guest" || identity.state === "signed_out" || identity.state === "error") && Boolean(identity.onSignIn);
|
|
1715
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SidebarMenu, { className: "w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(SidebarMenuItem, { className: "w-full min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenu, { children: [
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
1717
|
+
SidebarMenuButton,
|
|
1718
|
+
{
|
|
1719
|
+
size: "lg",
|
|
1720
|
+
"aria-label": `Account: ${label}`,
|
|
1721
|
+
className: "w-full min-w-0 justify-start",
|
|
1722
|
+
children: [
|
|
1723
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(IdentityAvatar, { identity }),
|
|
1724
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("span", { className: "min-w-0 flex-1 overflow-hidden text-start", children: [
|
|
1725
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block truncate text-sm font-medium", children: label }),
|
|
1726
|
+
identity.secondaryText ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block truncate text-xs text-muted-foreground", children: identity.secondaryText }) : null
|
|
1727
|
+
] })
|
|
1728
|
+
]
|
|
1729
|
+
}
|
|
1730
|
+
) }),
|
|
1731
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenuContent, { align: "start", side: "top", sideOffset: 8, children: [
|
|
1732
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenuLabel, { children: [
|
|
1733
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "block truncate", children: label }),
|
|
1734
|
+
identity.secondaryText ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "mt-0.5 block truncate text-xs font-normal text-muted-foreground", children: identity.secondaryText }) : null
|
|
1735
|
+
] }),
|
|
1736
|
+
canSignIn || canSignOut ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(DropdownMenuSeparator, {}) : null,
|
|
1737
|
+
canSignIn ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenuItem, { onSelect: () => identity.onSignIn?.(), children: [
|
|
1738
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.LogIn, {}),
|
|
1739
|
+
"Sign in"
|
|
1740
|
+
] }) : null,
|
|
1741
|
+
canSignOut ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(DropdownMenuItem, { onSelect: () => identity.onSignOut?.(), children: [
|
|
1742
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react9.LogOut, {}),
|
|
1743
|
+
"Sign out"
|
|
1744
|
+
] }) : null
|
|
1745
|
+
] })
|
|
1746
|
+
] }) }) });
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
// scaffold/src/components/chat/thread-sidebar.tsx
|
|
1750
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1751
|
+
function ThreadStatus({ thread }) {
|
|
1752
|
+
const activity = (0, import_react.getThreadActivity)(thread);
|
|
1753
|
+
if (!activity.isSpinning) return null;
|
|
1754
|
+
const label = activity.status === "cancelling" ? "Cancelling" : activity.status === "queued" ? "Queued" : "Running";
|
|
1755
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1756
|
+
"span",
|
|
1757
|
+
{
|
|
1758
|
+
className: "pointer-events-none absolute end-1 top-1/2 hidden size-5 -translate-y-1/2 items-center justify-center text-muted-foreground transition-opacity group-hover/menu-item:opacity-0 md:flex",
|
|
1759
|
+
role: "status",
|
|
1760
|
+
"aria-label": label,
|
|
1761
|
+
title: label,
|
|
1762
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.LoaderCircle, { className: "size-3.5 animate-spin" })
|
|
1763
|
+
}
|
|
1764
|
+
);
|
|
1765
|
+
}
|
|
1766
|
+
function ThreadSidebar({ activeThreadId, hasMore, identity, isLoading, isLoadingMore, onDelete, onLoadMore, onNew, onOpen, threads }) {
|
|
1767
|
+
const { setOpenMobile } = useSidebar();
|
|
1768
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
1769
|
+
Sidebar,
|
|
1770
|
+
{
|
|
1771
|
+
"aria-label": "Conversations",
|
|
1772
|
+
collapsible: "offcanvas",
|
|
1773
|
+
"data-agents24-chat-sidebar": "",
|
|
1774
|
+
role: "navigation",
|
|
1775
|
+
children: [
|
|
1776
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(SidebarHeader, { className: "gap-1 p-2", children: [
|
|
1777
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "h-8 shrink-0", "aria-hidden": "true" }),
|
|
1778
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Button, { className: "w-full justify-start", variant: "ghost", onClick: () => {
|
|
1779
|
+
onNew();
|
|
1780
|
+
setOpenMobile(false);
|
|
1781
|
+
}, children: [
|
|
1782
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.SquarePen, {}),
|
|
1783
|
+
" New chat"
|
|
1784
|
+
] })
|
|
1785
|
+
] }),
|
|
1786
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarContent, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarGroup, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(SidebarGroupContent, { children: [
|
|
1787
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarMenu, { children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(SidebarMenuItem, { children: [
|
|
1788
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1789
|
+
SidebarMenuButton,
|
|
1790
|
+
{
|
|
1791
|
+
className: "pr-8 pl-3",
|
|
1792
|
+
isActive: thread.id === activeThreadId,
|
|
1793
|
+
title: String(thread.title || "New conversation"),
|
|
1794
|
+
onClick: () => {
|
|
1795
|
+
void onOpen(thread.id).catch(() => void 0);
|
|
1796
|
+
setOpenMobile(false);
|
|
1797
|
+
},
|
|
1798
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "min-w-0 truncate", children: String(thread.title || "New conversation") })
|
|
1799
|
+
}
|
|
1800
|
+
),
|
|
1801
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ThreadStatus, { thread }),
|
|
1802
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1803
|
+
SidebarMenuAction,
|
|
1804
|
+
{
|
|
1805
|
+
showOnHover: true,
|
|
1806
|
+
className: "group-focus-within/menu-item:opacity-0 group-hover/menu-item:opacity-100",
|
|
1807
|
+
"aria-label": `Delete ${String(thread.title || "conversation")}`,
|
|
1808
|
+
onClick: (event) => {
|
|
1809
|
+
event.stopPropagation();
|
|
1810
|
+
if (window.confirm("Delete this conversation?")) void onDelete(thread.id).catch(() => void 0);
|
|
1811
|
+
},
|
|
1812
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.Trash2, {})
|
|
1813
|
+
}
|
|
1814
|
+
)
|
|
1815
|
+
] }, thread.id)) }),
|
|
1816
|
+
!isLoading && threads.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "px-2 py-8 text-center text-xs text-muted-foreground", children: "No conversations" }),
|
|
1817
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
1818
|
+
Button,
|
|
1819
|
+
{
|
|
1820
|
+
className: "mt-2 w-full",
|
|
1821
|
+
disabled: isLoadingMore,
|
|
1822
|
+
size: "sm",
|
|
1823
|
+
variant: "ghost",
|
|
1824
|
+
onClick: () => void onLoadMore().catch(() => void 0),
|
|
1825
|
+
children: [
|
|
1826
|
+
isLoadingMore && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react10.LoaderCircle, { className: "animate-spin" }),
|
|
1827
|
+
"Load more"
|
|
1828
|
+
]
|
|
1829
|
+
}
|
|
1830
|
+
)
|
|
1831
|
+
] }) }) }),
|
|
1832
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarFooter, { className: "w-full min-w-0 p-2", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(IdentityControl, { identity }) }),
|
|
1833
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarRail, {})
|
|
1834
|
+
]
|
|
1835
|
+
}
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
// scaffold/src/components/chat/turn-outline.tsx
|
|
1840
|
+
var import_react2 = require("react");
|
|
1841
|
+
|
|
1842
|
+
// scaffold/src/components/ui/message-scroller.tsx
|
|
1843
|
+
var import_message_scroller = require("@shadcn/react/message-scroller");
|
|
1844
|
+
var import_lucide_react11 = require("lucide-react");
|
|
1845
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1846
|
+
function MessageScrollerProvider(props) {
|
|
1847
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_message_scroller.MessageScroller.Provider, { ...props });
|
|
1848
|
+
}
|
|
1849
|
+
function MessageScroller({
|
|
1850
|
+
className,
|
|
1851
|
+
...props
|
|
1852
|
+
}) {
|
|
1853
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1854
|
+
import_message_scroller.MessageScroller.Root,
|
|
1855
|
+
{
|
|
1856
|
+
"data-slot": "message-scroller",
|
|
1857
|
+
className: cn(
|
|
1858
|
+
"group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden",
|
|
1859
|
+
className
|
|
1860
|
+
),
|
|
1861
|
+
...props
|
|
1862
|
+
}
|
|
1863
|
+
);
|
|
1864
|
+
}
|
|
1865
|
+
function MessageScrollerViewport({
|
|
1866
|
+
className,
|
|
1867
|
+
...props
|
|
1868
|
+
}) {
|
|
1869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1870
|
+
import_message_scroller.MessageScroller.Viewport,
|
|
1871
|
+
{
|
|
1872
|
+
"data-slot": "message-scroller-viewport",
|
|
1873
|
+
className: cn(
|
|
1874
|
+
"size-full min-h-0 min-w-0 scroll-fade-b overflow-y-auto overscroll-contain contain-content [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
|
|
1875
|
+
className
|
|
1876
|
+
),
|
|
1877
|
+
...props
|
|
1878
|
+
}
|
|
1879
|
+
);
|
|
1880
|
+
}
|
|
1881
|
+
function MessageScrollerContent({
|
|
1882
|
+
className,
|
|
1883
|
+
...props
|
|
1884
|
+
}) {
|
|
1885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1886
|
+
import_message_scroller.MessageScroller.Content,
|
|
1887
|
+
{
|
|
1888
|
+
"data-slot": "message-scroller-content",
|
|
1889
|
+
className: cn("flex h-max min-h-full flex-col gap-8", className),
|
|
1890
|
+
...props
|
|
1891
|
+
}
|
|
1892
|
+
);
|
|
1893
|
+
}
|
|
1894
|
+
function MessageScrollerItem({
|
|
1895
|
+
className,
|
|
1896
|
+
scrollAnchor = false,
|
|
1897
|
+
...props
|
|
1898
|
+
}) {
|
|
1899
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1900
|
+
import_message_scroller.MessageScroller.Item,
|
|
1901
|
+
{
|
|
1902
|
+
"data-slot": "message-scroller-item",
|
|
1903
|
+
scrollAnchor,
|
|
1904
|
+
className: cn(
|
|
1905
|
+
"min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]",
|
|
1906
|
+
className
|
|
1907
|
+
),
|
|
1908
|
+
...props
|
|
1909
|
+
}
|
|
1910
|
+
);
|
|
1911
|
+
}
|
|
1912
|
+
function MessageScrollerButton({
|
|
1913
|
+
direction = "end",
|
|
1914
|
+
className,
|
|
1915
|
+
children,
|
|
1916
|
+
render,
|
|
1917
|
+
variant = "secondary",
|
|
1918
|
+
size = "icon-sm",
|
|
1919
|
+
...props
|
|
1920
|
+
}) {
|
|
1921
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1922
|
+
import_message_scroller.MessageScroller.Button,
|
|
1923
|
+
{
|
|
1924
|
+
"data-slot": "message-scroller-button",
|
|
1925
|
+
"data-direction": direction,
|
|
1926
|
+
"data-variant": variant,
|
|
1927
|
+
"data-size": size,
|
|
1928
|
+
direction,
|
|
1929
|
+
className: cn(
|
|
1930
|
+
"absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180",
|
|
1931
|
+
className
|
|
1932
|
+
),
|
|
1933
|
+
render: render ?? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Button, { variant, size }),
|
|
1934
|
+
...props,
|
|
1935
|
+
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1936
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1937
|
+
import_lucide_react11.ArrowDownIcon,
|
|
1938
|
+
{}
|
|
1939
|
+
),
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only", children: direction === "end" ? "Scroll to end" : "Scroll to start" })
|
|
1941
|
+
] })
|
|
1942
|
+
}
|
|
1943
|
+
);
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
// scaffold/src/components/chat/turn-outline.tsx
|
|
1947
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1948
|
+
function turnsFromMessages(messages) {
|
|
1949
|
+
return messages.reduce((turns, message) => {
|
|
1950
|
+
if (message.role === "user") {
|
|
1951
|
+
turns.push({ id: message.id, label: message.content.trim() || `Turn ${turns.length + 1}`, messageIds: [message.id], response: "" });
|
|
1952
|
+
} else if (turns.length) {
|
|
1953
|
+
const turn = turns[turns.length - 1];
|
|
1954
|
+
turn.messageIds.push(message.id);
|
|
1955
|
+
if (!turn.response) turn.response = message.content.trim();
|
|
1956
|
+
}
|
|
1957
|
+
return turns;
|
|
1958
|
+
}, []);
|
|
1959
|
+
}
|
|
1960
|
+
function TurnOutline({ messages }) {
|
|
1961
|
+
const turns = turnsFromMessages(messages);
|
|
1962
|
+
const { scrollToMessage } = (0, import_message_scroller.useMessageScroller)();
|
|
1963
|
+
const { currentAnchorId, visibleMessageIds } = (0, import_message_scroller.useMessageScrollerVisibility)();
|
|
1964
|
+
const visible = new Set(visibleMessageIds);
|
|
1965
|
+
const [hoveredIndex, setHoveredIndex] = (0, import_react2.useState)(null);
|
|
1966
|
+
const focusIndex = hoveredIndex ?? -1;
|
|
1967
|
+
if (turns.length < 2) return null;
|
|
1968
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("nav", { "aria-label": "Transcript outline", className: "pointer-events-none absolute end-2 top-1/2 z-20 hidden max-h-72 w-14 -translate-y-1/2 md:block xl:end-5", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "pointer-events-auto flex flex-col items-end gap-0.5 py-2", children: turns.map((turn, index) => {
|
|
1969
|
+
const active = turn.messageIds.some((id) => visible.has(id) || currentAnchorId === id);
|
|
1970
|
+
const distance = focusIndex >= 0 ? Math.abs(index - focusIndex) : Number.POSITIVE_INFINITY;
|
|
1971
|
+
const barWidth = focusIndex < 0 ? 12 : distance === 0 ? 50 : distance === 1 ? 36 : distance === 2 ? 23 : 10;
|
|
1972
|
+
const barOpacity = focusIndex < 0 ? active ? 1 : 0.4 : distance === 0 ? 1 : distance === 1 ? 0.78 : distance === 2 ? 0.58 : 0.36;
|
|
1973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Tooltip, { children: [
|
|
1974
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1975
|
+
"button",
|
|
1976
|
+
{
|
|
1977
|
+
type: "button",
|
|
1978
|
+
"aria-label": `Jump to ${turn.label}`,
|
|
1979
|
+
className: "group relative flex h-2 w-14 items-center justify-end outline-none after:pointer-events-auto after:absolute after:-inset-y-0.5 after:inset-x-0 after:content-['']",
|
|
1980
|
+
onBlur: () => setHoveredIndex(null),
|
|
1981
|
+
onFocus: () => setHoveredIndex(index),
|
|
1982
|
+
onMouseEnter: () => setHoveredIndex(index),
|
|
1983
|
+
onMouseLeave: () => setHoveredIndex(null),
|
|
1984
|
+
onClick: () => scrollToMessage(turn.id, { align: "start", behavior: "smooth" }),
|
|
1985
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1986
|
+
"span",
|
|
1987
|
+
{
|
|
1988
|
+
className: cn("h-0.5 rounded-full bg-muted-foreground/40 transition-[width,background-color,opacity] duration-150 ease-out group-hover:bg-foreground group-focus-visible:bg-foreground", active && "bg-foreground"),
|
|
1989
|
+
style: { opacity: barOpacity, width: barWidth }
|
|
1990
|
+
}
|
|
1991
|
+
)
|
|
1992
|
+
}
|
|
1993
|
+
) }),
|
|
1994
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(TooltipContent, { side: "left", className: "w-64 flex-col items-stretch gap-0 overflow-hidden p-3", children: [
|
|
1995
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "line-clamp-2 max-w-full wrap-break-word text-sm font-medium", children: turn.label }),
|
|
1996
|
+
turn.response && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "mt-1 line-clamp-2 max-w-full wrap-break-word text-xs opacity-70", children: turn.response })
|
|
1997
|
+
] })
|
|
1998
|
+
] }, turn.id);
|
|
1999
|
+
}) }) });
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// scaffold/src/components/chat/timeline-loading.ts
|
|
2003
|
+
function isScaffoldTimelineLoading({
|
|
2004
|
+
activeRunId,
|
|
2005
|
+
message,
|
|
2006
|
+
runState,
|
|
2007
|
+
streamingMessageId
|
|
2008
|
+
}) {
|
|
2009
|
+
if (runState !== "streaming" && runState !== "reconnecting") return false;
|
|
2010
|
+
return message.id === streamingMessageId || Boolean(message.runId && message.runId === activeRunId);
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
// scaffold/src/components/chat/chat-shell.tsx
|
|
2014
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2015
|
+
var LOADING_INPUT_CONTRACT = {
|
|
2016
|
+
version: "agents24.runtime-inputs.v2",
|
|
2017
|
+
modalities: {
|
|
2018
|
+
text: { enabled: false, required: false },
|
|
2019
|
+
files: { enabled: false, required: false, allowed_mime_types: [] },
|
|
2020
|
+
images: { enabled: false, required: false, allowed_mime_types: [] },
|
|
2021
|
+
audio: { enabled: false, required: false, allowed_mime_types: [], recording_enabled: false }
|
|
2022
|
+
},
|
|
2023
|
+
limits: { max_attachments_per_turn: 0, max_file_bytes: 0, max_total_bytes: 0 },
|
|
2024
|
+
retention: { mode: "thread_lifetime" }
|
|
2025
|
+
};
|
|
2026
|
+
function PersistentSidebarTrigger() {
|
|
2027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "pointer-events-none fixed start-3 top-0 z-[60] flex h-12 items-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SidebarTrigger, { className: "pointer-events-auto [&_svg]:size-[18px]" }) });
|
|
2028
|
+
}
|
|
2029
|
+
function CollapsedHeaderActions({ onNew }) {
|
|
2030
|
+
const { isMobile, openMobile, state } = useSidebar();
|
|
2031
|
+
const sidebarVisible = isMobile ? openMobile : state === "expanded";
|
|
2032
|
+
if (sidebarVisible) return null;
|
|
2033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
2034
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "h-8 w-17 shrink-0", "aria-hidden": "true" }),
|
|
2035
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "pointer-events-none fixed start-12 top-0 z-[60] flex h-12 items-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { className: "pointer-events-auto", variant: "ghost", size: "icon-sm", "aria-label": "New chat", onClick: onNew, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.SquarePen, {}) }) })
|
|
2036
|
+
] });
|
|
2037
|
+
}
|
|
2038
|
+
function OperationErrorNotice({ runtime }) {
|
|
2039
|
+
const error = runtime.operationError || runtime.backgroundError;
|
|
2040
|
+
if (!error) return null;
|
|
2041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "pointer-events-none absolute inset-x-0 top-3 z-40 flex justify-center px-4", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "pointer-events-auto flex max-w-lg items-start gap-2 rounded-lg border border-destructive/20 bg-background px-3 py-2 text-sm shadow-md", role: "alert", children: [
|
|
2042
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.CircleAlert, { className: "mt-0.5 size-4 shrink-0 text-destructive" }),
|
|
2043
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "min-w-0 flex-1 wrap-break-word", children: (0, import_runtime2.agentChatRuntimeErrorMessage)(error) || "The chat could not complete that action." }),
|
|
2044
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2045
|
+
Button,
|
|
2046
|
+
{
|
|
2047
|
+
"aria-label": "Dismiss error",
|
|
2048
|
+
onClick: runtime.operationError ? runtime.clearOperationError : runtime.controller.clearBackgroundError,
|
|
2049
|
+
size: "icon-xs",
|
|
2050
|
+
variant: "ghost",
|
|
2051
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.X, {})
|
|
2052
|
+
}
|
|
2053
|
+
)
|
|
2054
|
+
] }) });
|
|
2055
|
+
}
|
|
2056
|
+
function ChatShell({
|
|
2057
|
+
components,
|
|
2058
|
+
identity,
|
|
2059
|
+
runtime
|
|
2060
|
+
}) {
|
|
2061
|
+
const { controller } = runtime;
|
|
2062
|
+
const isRunning = controller.runState === "streaming" || controller.runState === "reconnecting" || controller.runState === "paused" || controller.runState === "cancelling" || runtime.isSubmitting;
|
|
2063
|
+
const isCancelling = controller.runState === "cancelling";
|
|
2064
|
+
const activeTitle = controller.threads.find((thread) => thread.id === controller.activeThreadId)?.title;
|
|
2065
|
+
const hasBlockingError = Boolean(runtime.fatalError && controller.messages.length === 0);
|
|
2066
|
+
const isEmptyState = controller.activeThreadId === null && controller.messages.length === 0 && !hasBlockingError;
|
|
2067
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
2068
|
+
SidebarProvider,
|
|
2069
|
+
{
|
|
2070
|
+
className: "h-svh min-h-0 overflow-hidden",
|
|
2071
|
+
"data-agents24-chat": "",
|
|
2072
|
+
"data-agents24-chat-layout": "",
|
|
2073
|
+
children: [
|
|
2074
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PersistentSidebarTrigger, {}),
|
|
2075
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2076
|
+
ThreadSidebar,
|
|
2077
|
+
{
|
|
2078
|
+
activeThreadId: controller.activeThreadId,
|
|
2079
|
+
hasMore: controller.hasMoreThreads,
|
|
2080
|
+
identity,
|
|
2081
|
+
isLoading: controller.isLoadingThreads,
|
|
2082
|
+
isLoadingMore: controller.isLoadingMoreThreads,
|
|
2083
|
+
threads: controller.threads,
|
|
2084
|
+
onDelete: runtime.deleteThread,
|
|
2085
|
+
onLoadMore: controller.loadMoreThreads,
|
|
2086
|
+
onNew: runtime.newThread,
|
|
2087
|
+
onOpen: runtime.openThread
|
|
2088
|
+
}
|
|
2089
|
+
),
|
|
2090
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(SidebarInset, { className: "h-svh min-h-0 overflow-hidden bg-background", children: [
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
2092
|
+
"header",
|
|
2093
|
+
{
|
|
2094
|
+
className: "flex h-12 shrink-0 items-center gap-2 border-b border-border/30 px-3 sm:px-4",
|
|
2095
|
+
"data-agents24-chat-header": "",
|
|
2096
|
+
children: [
|
|
2097
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(CollapsedHeaderActions, { onNew: runtime.newThread }),
|
|
2098
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h1", { className: "truncate text-sm font-medium", children: String(activeTitle || "New chat") }) }),
|
|
2099
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(ThemeMenu, {})
|
|
2100
|
+
]
|
|
2101
|
+
}
|
|
2102
|
+
),
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
2104
|
+
"section",
|
|
2105
|
+
{
|
|
2106
|
+
"aria-label": "Conversation",
|
|
2107
|
+
className: "relative flex min-h-0 flex-1 flex-col overflow-hidden",
|
|
2108
|
+
"data-agents24-chat-transcript": "",
|
|
2109
|
+
children: [
|
|
2110
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(OperationErrorNotice, { runtime }),
|
|
2111
|
+
isEmptyState ? /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "absolute inset-0 flex min-h-0 flex-col justify-center pb-20", children: [
|
|
2112
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "mx-auto mb-8 w-full max-w-3xl px-4 text-center sm:px-6", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { className: "text-3xl font-semibold tracking-tight sm:text-4xl", children: "Ready when you are." }) }),
|
|
2113
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2114
|
+
ChatComposer,
|
|
2115
|
+
{
|
|
2116
|
+
inputContract: runtime.inputContract || LOADING_INPUT_CONTRACT,
|
|
2117
|
+
contextWindow: runtime.contextWindow,
|
|
2118
|
+
disabled: runtime.isBootstrapping,
|
|
2119
|
+
forceExpanded: true,
|
|
2120
|
+
isCancelling,
|
|
2121
|
+
isRunning,
|
|
2122
|
+
onStop: () => {
|
|
2123
|
+
void controller.cancelRun().catch(() => void 0);
|
|
2124
|
+
},
|
|
2125
|
+
modelId: runtime.modelId,
|
|
2126
|
+
models: runtime.models,
|
|
2127
|
+
onModelChange: runtime.changeModel,
|
|
2128
|
+
onSubmit: (text, files) => runtime.submit({
|
|
2129
|
+
text,
|
|
2130
|
+
files: files.map((file) => ({
|
|
2131
|
+
data: file,
|
|
2132
|
+
mediaType: file.type || "application/octet-stream",
|
|
2133
|
+
name: file.name
|
|
2134
|
+
}))
|
|
2135
|
+
})
|
|
2136
|
+
}
|
|
2137
|
+
)
|
|
2138
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
2139
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2140
|
+
MessageScrollerProvider,
|
|
2141
|
+
{
|
|
2142
|
+
autoScroll: true,
|
|
2143
|
+
defaultScrollPosition: "last-anchor",
|
|
2144
|
+
scrollPreviousItemPeek: 64,
|
|
2145
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(MessageScroller, { className: "relative min-h-0 flex-1", children: [
|
|
2146
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MessageScrollerViewport, { preserveScrollOnPrepend: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
2147
|
+
MessageScrollerContent,
|
|
2148
|
+
{
|
|
2149
|
+
className: "mx-auto w-full max-w-3xl gap-7 px-4 pt-8 pb-16 sm:px-6 sm:pt-12",
|
|
2150
|
+
children: [
|
|
2151
|
+
controller.hasOlderTurns && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Button, { className: "self-center", variant: "ghost", size: "sm", disabled: controller.isLoadingOlder, onClick: () => {
|
|
2152
|
+
void controller.loadOlder().catch(() => void 0);
|
|
2153
|
+
}, children: [
|
|
2154
|
+
controller.isLoadingOlder && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.LoaderCircle, { className: "animate-spin" }),
|
|
2155
|
+
" Load earlier messages"
|
|
2156
|
+
] }),
|
|
2157
|
+
runtime.isBootstrapping && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { "aria-label": "Loading conversation", className: "flex flex-1 items-center justify-center py-24 text-muted-foreground", role: "status", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.LoaderCircle, { className: "size-4 animate-spin" }) }),
|
|
2158
|
+
hasBlockingError && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 py-24 text-center", children: [
|
|
2159
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react12.CircleAlert, { className: "size-5 text-destructive" }),
|
|
2160
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { children: [
|
|
2161
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { className: "font-medium", children: "Couldn\u2019t connect" }),
|
|
2162
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "mt-1 max-w-md text-sm text-muted-foreground", children: runtime.errorMessage })
|
|
2163
|
+
] }),
|
|
2164
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { variant: "outline", onClick: () => void runtime.retryBootstrap(), children: "Try again" })
|
|
2165
|
+
] }),
|
|
2166
|
+
controller.messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2167
|
+
MessageScrollerItem,
|
|
2168
|
+
{
|
|
2169
|
+
messageId: message.id,
|
|
2170
|
+
scrollAnchor: message.role === "user",
|
|
2171
|
+
className: "overflow-visible [content-visibility:visible]",
|
|
2172
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2173
|
+
ChatMessage,
|
|
2174
|
+
{
|
|
2175
|
+
allowFeedback: runtime.allowFeedback,
|
|
2176
|
+
getHitlActionState: runtime.getHitlActionState,
|
|
2177
|
+
isLoading: isScaffoldTimelineLoading({
|
|
2178
|
+
activeRunId: controller.activeRunId,
|
|
2179
|
+
message,
|
|
2180
|
+
runState: controller.runState,
|
|
2181
|
+
streamingMessageId: controller.streamingMessageId
|
|
2182
|
+
}),
|
|
2183
|
+
message,
|
|
2184
|
+
onHitlAction: runtime.onHitlAction,
|
|
2185
|
+
onRegenerate: () => controller.regenerate(message),
|
|
2186
|
+
onSetFeedback: (input) => controller.setFeedback(message, input),
|
|
2187
|
+
Timeline: components?.Timeline
|
|
2188
|
+
}
|
|
2189
|
+
)
|
|
2190
|
+
},
|
|
2191
|
+
message.id
|
|
2192
|
+
))
|
|
2193
|
+
]
|
|
2194
|
+
}
|
|
2195
|
+
) }),
|
|
2196
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TurnOutline, { messages: controller.messages }),
|
|
2197
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(MessageScrollerButton, {})
|
|
2198
|
+
] })
|
|
2199
|
+
}
|
|
2200
|
+
),
|
|
2201
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "relative z-30 shrink-0 bg-background pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2202
|
+
ChatComposer,
|
|
2203
|
+
{
|
|
2204
|
+
inputContract: runtime.inputContract || LOADING_INPUT_CONTRACT,
|
|
2205
|
+
contextWindow: runtime.contextWindow,
|
|
2206
|
+
disabled: runtime.isBootstrapping || hasBlockingError,
|
|
2207
|
+
isCancelling,
|
|
2208
|
+
isRunning,
|
|
2209
|
+
onStop: () => {
|
|
2210
|
+
void controller.cancelRun().catch(() => void 0);
|
|
2211
|
+
},
|
|
2212
|
+
modelId: runtime.modelId,
|
|
2213
|
+
models: runtime.models,
|
|
2214
|
+
onModelChange: runtime.changeModel,
|
|
2215
|
+
onSubmit: (text, files) => runtime.submit({
|
|
2216
|
+
text,
|
|
2217
|
+
files: files.map((file) => ({
|
|
2218
|
+
data: file,
|
|
2219
|
+
mediaType: file.type || "application/octet-stream",
|
|
2220
|
+
name: file.name
|
|
2221
|
+
}))
|
|
2222
|
+
}),
|
|
2223
|
+
utilityRow: "below"
|
|
2224
|
+
}
|
|
2225
|
+
) })
|
|
2226
|
+
] })
|
|
2227
|
+
]
|
|
2228
|
+
}
|
|
2229
|
+
)
|
|
2230
|
+
] })
|
|
2231
|
+
]
|
|
2232
|
+
}
|
|
2233
|
+
);
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
// scaffold/src/identity.ts
|
|
2237
|
+
var GUEST_CHAT_IDENTITY = { state: "guest" };
|
|
2238
|
+
|
|
2239
|
+
// scaffold/src/app.tsx
|
|
2240
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2241
|
+
var createBrowserAbortController = () => new AbortController();
|
|
2242
|
+
function RuntimeChat({
|
|
2243
|
+
components,
|
|
2244
|
+
identity = GUEST_CHAT_IDENTITY,
|
|
2245
|
+
...props
|
|
2246
|
+
}) {
|
|
2247
|
+
const runtime = (0, import_runtime3.useAgentChatRuntime)({
|
|
2248
|
+
...props,
|
|
2249
|
+
mcpRedirectUri: props.mcpRedirectUri || (typeof window === "undefined" ? void 0 : window.location.href)
|
|
2250
|
+
});
|
|
2251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ChatShell, { components, identity, runtime });
|
|
2252
|
+
}
|
|
2253
|
+
function App(props) {
|
|
2254
|
+
const identity = props.identity || GUEST_CHAT_IDENTITY;
|
|
2255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_react3.Agents24Provider, { client: props.client, createAbortController: createBrowserAbortController, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(RuntimeChat, { ...props }, identity.state) });
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
// scaffold/src/index.tsx
|
|
2259
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2260
|
+
function Agents24ChatScaffold({ appearanceController, theme, ...props }) {
|
|
2261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ThemeProvider, { controller: appearanceController, theme, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(App, { ...props }) }) });
|
|
2262
|
+
}
|
|
2263
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
2264
|
+
0 && (module.exports = {
|
|
2265
|
+
Agents24ChatScaffold,
|
|
2266
|
+
Agents24ChatScaffoldApp,
|
|
2267
|
+
Agents24ChatThemeProvider,
|
|
2268
|
+
Agents24ChatTooltipProvider
|
|
2269
|
+
});
|
|
2270
|
+
//# sourceMappingURL=index.cjs.map
|