@slipstream-ui/ai 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +51 -4
- package/dist/index.d.ts +51 -4
- package/dist/index.js +244 -113
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +246 -115
- package/dist/index.mjs.map +1 -1
- package/dist/manifests/attachment.manifest.json +37 -8
- package/dist/manifests/branch.manifest.json +3 -1
- package/dist/manifests/chain-thought.manifest.json +1 -1
- package/dist/manifests/code-block.manifest.json +3 -1
- package/dist/manifests/command-palette.manifest.json +59 -4
- package/dist/manifests/confirmation.manifest.json +3 -1
- package/dist/manifests/conversation.manifest.json +1 -1
- package/dist/manifests/inline-citation.manifest.json +3 -1
- package/dist/manifests/message-actions.manifest.json +61 -10
- package/dist/manifests/message.manifest.json +13 -1
- package/dist/manifests/prompt-input.manifest.json +2 -2
- package/dist/manifests/reasoning.manifest.json +19 -1
- package/dist/manifests/response.manifest.json +3 -1
- package/dist/manifests/source.manifest.json +2 -2
- package/dist/manifests/streaming-indicator.manifest.json +1 -1
- package/dist/manifests/suggestions.manifest.json +2 -2
- package/dist/manifests/tool-call.manifest.json +7 -1
- package/package.json +10 -10
- package/src/components/code-block/CodeBlock.tsx +91 -5
- package/src/components/command-palette/CommandPalette.test.tsx +42 -0
- package/src/components/command-palette/CommandPalette.tsx +82 -8
- package/src/components/confirmation/Confirmation.tsx +1 -1
- package/src/components/conversation/Conversation.tsx +6 -1
- package/src/components/message/Message.test.tsx +15 -0
- package/src/components/message/Message.tsx +9 -1
- package/src/components/reasoning/Reasoning.test.tsx +15 -0
- package/src/components/reasoning/Reasoning.tsx +20 -7
- package/src/components/tool-call/ToolCall.tsx +24 -8
- package/src/manifests/attachment.manifest.json +37 -8
- package/src/manifests/branch.manifest.json +3 -1
- package/src/manifests/chain-thought.manifest.json +1 -1
- package/src/manifests/code-block.manifest.json +3 -1
- package/src/manifests/command-palette.manifest.json +59 -4
- package/src/manifests/confirmation.manifest.json +3 -1
- package/src/manifests/conversation.manifest.json +1 -1
- package/src/manifests/inline-citation.manifest.json +3 -1
- package/src/manifests/message-actions.manifest.json +61 -10
- package/src/manifests/message.manifest.json +13 -1
- package/src/manifests/prompt-input.manifest.json +2 -2
- package/src/manifests/reasoning.manifest.json +19 -1
- package/src/manifests/response.manifest.json +3 -1
- package/src/manifests/source.manifest.json +2 -2
- package/src/manifests/streaming-indicator.manifest.json +1 -1
- package/src/manifests/suggestions.manifest.json +2 -2
- package/src/manifests/tool-call.manifest.json +7 -1
package/dist/index.mjs
CHANGED
|
@@ -14,6 +14,8 @@ var Message = React.forwardRef(
|
|
|
14
14
|
avatarFallback,
|
|
15
15
|
userLabel = "You",
|
|
16
16
|
assistantLabel = "Assistant",
|
|
17
|
+
formatTime,
|
|
18
|
+
locale,
|
|
17
19
|
renderContent,
|
|
18
20
|
isStreaming = false,
|
|
19
21
|
error,
|
|
@@ -67,7 +69,7 @@ var Message = React.forwardRef(
|
|
|
67
69
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
68
70
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
69
71
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: displayLabel }),
|
|
70
|
-
message.timestamp && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: new Date(message.timestamp).toLocaleTimeString() })
|
|
72
|
+
message.timestamp && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: formatTime ? formatTime(new Date(message.timestamp)) : new Date(message.timestamp).toLocaleTimeString(locale) })
|
|
71
73
|
] }),
|
|
72
74
|
error ? /* @__PURE__ */ jsxs("div", { role: "alert", className: "text-sm", children: [
|
|
73
75
|
/* @__PURE__ */ jsx("div", { className: "text-destructive mb-2", children: error }),
|
|
@@ -292,7 +294,7 @@ import { cn as cn6 } from "@slipstream-ui/core";
|
|
|
292
294
|
|
|
293
295
|
// src/components/code-block/CodeBlock.tsx
|
|
294
296
|
import * as React5 from "react";
|
|
295
|
-
import { Highlight
|
|
297
|
+
import { Highlight } from "prism-react-renderer";
|
|
296
298
|
import { cn as cn5 } from "@slipstream-ui/core";
|
|
297
299
|
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
298
300
|
function useIsDark() {
|
|
@@ -306,11 +308,80 @@ function useIsDark() {
|
|
|
306
308
|
}, []);
|
|
307
309
|
return dark;
|
|
308
310
|
}
|
|
311
|
+
var LIGHT_CODE_THEME = {
|
|
312
|
+
plain: { color: "#1f2328", backgroundColor: "transparent" },
|
|
313
|
+
styles: [
|
|
314
|
+
{ types: ["comment", "prolog", "doctype", "cdata"], style: { color: "#57606a" } },
|
|
315
|
+
{ types: ["punctuation", "operator"], style: { color: "#24292f" } },
|
|
316
|
+
{ types: ["namespace"], style: { color: "#6f42c1" } },
|
|
317
|
+
{ types: ["tag", "deleted", "keyword", "atrule", "important"], style: { color: "#b31d28" } },
|
|
318
|
+
{ types: ["attr-name", "variable"], style: { color: "#953800" } },
|
|
319
|
+
{ types: ["string", "char", "attr-value", "inserted", "regex"], style: { color: "#0a5c2f" } },
|
|
320
|
+
{
|
|
321
|
+
types: [
|
|
322
|
+
"function",
|
|
323
|
+
"class-name",
|
|
324
|
+
"number",
|
|
325
|
+
"boolean",
|
|
326
|
+
"constant",
|
|
327
|
+
"symbol",
|
|
328
|
+
"property",
|
|
329
|
+
"selector",
|
|
330
|
+
"builtin",
|
|
331
|
+
"entity",
|
|
332
|
+
"url"
|
|
333
|
+
],
|
|
334
|
+
style: { color: "#0550ae" }
|
|
335
|
+
}
|
|
336
|
+
]
|
|
337
|
+
};
|
|
338
|
+
var DARK_CODE_THEME = {
|
|
339
|
+
plain: { color: "#e6edf3", backgroundColor: "transparent" },
|
|
340
|
+
styles: [
|
|
341
|
+
{ types: ["comment", "prolog", "doctype", "cdata"], style: { color: "#8b949e" } },
|
|
342
|
+
{ types: ["punctuation", "operator"], style: { color: "#c9d1d9" } },
|
|
343
|
+
{ types: ["namespace"], style: { color: "#d2a8ff" } },
|
|
344
|
+
{ types: ["tag", "deleted", "keyword", "atrule", "important"], style: { color: "#ff7b72" } },
|
|
345
|
+
{ types: ["attr-name", "variable"], style: { color: "#ffa657" } },
|
|
346
|
+
{ types: ["string", "char", "attr-value", "inserted", "regex"], style: { color: "#7ee787" } },
|
|
347
|
+
{
|
|
348
|
+
types: [
|
|
349
|
+
"function",
|
|
350
|
+
"class-name",
|
|
351
|
+
"number",
|
|
352
|
+
"boolean",
|
|
353
|
+
"constant",
|
|
354
|
+
"symbol",
|
|
355
|
+
"property",
|
|
356
|
+
"selector",
|
|
357
|
+
"builtin",
|
|
358
|
+
"entity",
|
|
359
|
+
"url"
|
|
360
|
+
],
|
|
361
|
+
style: { color: "#79c0ff" }
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
};
|
|
309
365
|
var CodeBlock = React5.forwardRef(
|
|
310
366
|
({ code, language = "tsx", showCopyButton = true, className, ...props }, ref) => {
|
|
311
367
|
const [copied, setCopied] = React5.useState(false);
|
|
312
368
|
const isDark = useIsDark();
|
|
313
369
|
const trimmedCode = code.replace(/\n$/, "");
|
|
370
|
+
const preRef = React5.useRef(null);
|
|
371
|
+
const [scrollable, setScrollable] = React5.useState(false);
|
|
372
|
+
React5.useEffect(() => {
|
|
373
|
+
const element = preRef.current;
|
|
374
|
+
if (!element) return;
|
|
375
|
+
const update = () => setScrollable(element.scrollWidth > element.clientWidth + 1);
|
|
376
|
+
update();
|
|
377
|
+
if (typeof ResizeObserver === "undefined") {
|
|
378
|
+
window.addEventListener("resize", update);
|
|
379
|
+
return () => window.removeEventListener("resize", update);
|
|
380
|
+
}
|
|
381
|
+
const observer = new ResizeObserver(update);
|
|
382
|
+
observer.observe(element);
|
|
383
|
+
return () => observer.disconnect();
|
|
384
|
+
}, [trimmedCode, language]);
|
|
314
385
|
const handleCopy = async () => {
|
|
315
386
|
try {
|
|
316
387
|
await navigator.clipboard.writeText(trimmedCode);
|
|
@@ -324,8 +395,8 @@ var CodeBlock = React5.forwardRef(
|
|
|
324
395
|
{
|
|
325
396
|
ref,
|
|
326
397
|
className: cn5(
|
|
327
|
-
// bg-background (not muted):
|
|
328
|
-
// surface
|
|
398
|
+
// bg-background (not muted): the light syntax palette is tuned for
|
|
399
|
+
// a white surface; on gray the token contrast drops below AA.
|
|
329
400
|
"relative group rounded-md border border-border bg-background overflow-hidden",
|
|
330
401
|
className
|
|
331
402
|
),
|
|
@@ -344,10 +415,13 @@ var CodeBlock = React5.forwardRef(
|
|
|
344
415
|
}
|
|
345
416
|
)
|
|
346
417
|
] }),
|
|
347
|
-
/* @__PURE__ */ jsx5(Highlight, { theme: isDark ?
|
|
418
|
+
/* @__PURE__ */ jsx5(Highlight, { theme: isDark ? DARK_CODE_THEME : LIGHT_CODE_THEME, code: trimmedCode, language, children: ({ style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx5(
|
|
348
419
|
"pre",
|
|
349
420
|
{
|
|
350
|
-
|
|
421
|
+
ref: preRef,
|
|
422
|
+
tabIndex: scrollable ? 0 : void 0,
|
|
423
|
+
"aria-label": scrollable ? `${language} code, scrollable` : void 0,
|
|
424
|
+
className: "overflow-x-auto p-4 text-xs leading-relaxed m-0 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
351
425
|
style: { ...style, background: "transparent" },
|
|
352
426
|
children: tokens.map((line, i) => /* @__PURE__ */ jsx5("div", { ...getLineProps({ line }), children: line.map((token, key) => /* @__PURE__ */ jsx5("span", { ...getTokenProps({ token }) }, key)) }, i))
|
|
353
427
|
}
|
|
@@ -444,7 +518,7 @@ import { Button as Button2 } from "@slipstream-ui/core";
|
|
|
444
518
|
import { cn as cn7 } from "@slipstream-ui/core";
|
|
445
519
|
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
446
520
|
var statusChipClasses = {
|
|
447
|
-
pending: "bg-warning/10 text-warning border-warning/20",
|
|
521
|
+
pending: "bg-warning/10 text-warning-ink border-warning/20",
|
|
448
522
|
approved: "bg-success/10 text-success border-success/20",
|
|
449
523
|
rejected: "bg-destructive/10 text-destructive border-destructive/20"
|
|
450
524
|
};
|
|
@@ -744,62 +818,71 @@ var Conversation = React10.forwardRef(
|
|
|
744
818
|
};
|
|
745
819
|
const isEmpty = messages.length === 0 && !isLoading;
|
|
746
820
|
return /* @__PURE__ */ jsxs8("div", { ref, className: cn10("relative h-full w-full", className), ...props, children: [
|
|
747
|
-
/* @__PURE__ */ jsxs8(
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
children:
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
821
|
+
/* @__PURE__ */ jsxs8(
|
|
822
|
+
"div",
|
|
823
|
+
{
|
|
824
|
+
ref: scrollRef,
|
|
825
|
+
tabIndex: 0,
|
|
826
|
+
"aria-label": "Conversation transcript",
|
|
827
|
+
className: "flex flex-col gap-4 p-4 overflow-y-auto h-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
828
|
+
children: [
|
|
829
|
+
(hasMoreHistory || isLoadingMore) && /* @__PURE__ */ jsx10(
|
|
830
|
+
"button",
|
|
831
|
+
{
|
|
832
|
+
type: "button",
|
|
833
|
+
onClick: handleLoadMore,
|
|
834
|
+
disabled: isLoadingMore,
|
|
835
|
+
className: "mx-auto rounded-full border border-border bg-background px-3 py-1 text-xs text-muted-foreground hover:text-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:opacity-50",
|
|
836
|
+
children: isLoadingMore ? "Loading\u2026" : "Load earlier messages"
|
|
837
|
+
}
|
|
838
|
+
),
|
|
839
|
+
isEmpty ? /* @__PURE__ */ jsxs8("div", { className: "flex flex-1 flex-col items-center justify-center gap-3 text-center py-16", children: [
|
|
840
|
+
/* @__PURE__ */ jsx10("h3", { className: "text-lg font-semibold", children: welcomeTitle }),
|
|
841
|
+
/* @__PURE__ */ jsx10("p", { className: "text-sm text-muted-foreground max-w-sm", children: welcomeDescription }),
|
|
842
|
+
welcomeSuggestions.length > 0 && /* @__PURE__ */ jsx10("div", { className: "mt-2 flex flex-col gap-2 w-full max-w-sm", children: welcomeSuggestions.map((suggestion) => /* @__PURE__ */ jsx10(
|
|
843
|
+
"button",
|
|
844
|
+
{
|
|
845
|
+
type: "button",
|
|
846
|
+
onClick: () => onWelcomeSelect?.(suggestion),
|
|
847
|
+
className: "rounded-md border border-border bg-background px-4 py-2.5 text-sm text-left text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
848
|
+
children: suggestion
|
|
849
|
+
},
|
|
850
|
+
suggestion
|
|
851
|
+
)) })
|
|
852
|
+
] }) : messages.map((message) => /* @__PURE__ */ jsx10(
|
|
853
|
+
MemoizedMessage,
|
|
854
|
+
{
|
|
855
|
+
message,
|
|
856
|
+
showAvatar: showAvatars,
|
|
857
|
+
avatarSrc: message.role === "user" ? userAvatarSrc : assistantAvatarSrc,
|
|
858
|
+
avatarFallback: message.role === "user" ? userAvatarFallback : assistantAvatarFallback,
|
|
859
|
+
renderContent,
|
|
860
|
+
isStreaming: message.id === streamingMessageId,
|
|
861
|
+
error: messageErrors?.[message.id],
|
|
862
|
+
onRetry: onRetryMessage && messageErrors?.[message.id] ? () => onRetryMessage(message) : void 0
|
|
863
|
+
},
|
|
864
|
+
message.id
|
|
865
|
+
)),
|
|
866
|
+
isLoading && !isEmpty && /* @__PURE__ */ jsx10(
|
|
867
|
+
MemoizedMessage,
|
|
868
|
+
{
|
|
869
|
+
message: {
|
|
870
|
+
id: "__loading__",
|
|
871
|
+
role: "assistant",
|
|
872
|
+
content: loadingMessage
|
|
873
|
+
},
|
|
874
|
+
showAvatar: showAvatars,
|
|
875
|
+
avatarSrc: assistantAvatarSrc,
|
|
876
|
+
avatarFallback: assistantAvatarFallback,
|
|
877
|
+
className: "bg-muted/50",
|
|
878
|
+
renderContent: (content) => /* @__PURE__ */ jsx10("span", { className: "text-muted-foreground animate-pulse motion-reduce:animate-none", children: content })
|
|
879
|
+
}
|
|
880
|
+
),
|
|
881
|
+
/* @__PURE__ */ jsx10("div", { "aria-live": "polite", className: "sr-only", children: announcement }),
|
|
882
|
+
/* @__PURE__ */ jsx10("div", { ref: messagesEndRef })
|
|
883
|
+
]
|
|
884
|
+
}
|
|
885
|
+
),
|
|
803
886
|
showDownload && messages.length > 0 && /* @__PURE__ */ jsx10(
|
|
804
887
|
"button",
|
|
805
888
|
{
|
|
@@ -1210,17 +1293,17 @@ import * as React12 from "react";
|
|
|
1210
1293
|
import { cn as cn12 } from "@slipstream-ui/core";
|
|
1211
1294
|
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1212
1295
|
var Reasoning = React12.forwardRef(
|
|
1213
|
-
({ steps, className, collapsible = true, defaultExpanded = false, duration, isStreaming = false, ...props }, ref) => {
|
|
1296
|
+
({ steps, className, collapsible = true, defaultExpanded = false, duration, isStreaming = false, labels, formatTime, locale, ...props }, ref) => {
|
|
1214
1297
|
const [isExpanded, setIsExpanded] = React12.useState(defaultExpanded);
|
|
1215
1298
|
const contentId = React12.useId();
|
|
1216
1299
|
if (steps.length === 0) {
|
|
1217
1300
|
return null;
|
|
1218
1301
|
}
|
|
1219
1302
|
const headerText = [
|
|
1220
|
-
"Reasoning",
|
|
1221
|
-
`(${steps.length} ${steps.length === 1 ? "step" : "steps"})`,
|
|
1303
|
+
labels?.title ?? "Reasoning",
|
|
1304
|
+
labels?.count ? labels.count(steps.length) : `(${steps.length} ${steps.length === 1 ? "step" : "steps"})`,
|
|
1222
1305
|
typeof duration === "number" ? `\xB7 ${duration}s` : duration ? `\xB7 ${duration}` : "",
|
|
1223
|
-
isStreaming ?
|
|
1306
|
+
isStreaming ? `\xB7 ${labels?.thinking ?? "thinking\u2026"}` : ""
|
|
1224
1307
|
].filter(Boolean).join(" ");
|
|
1225
1308
|
return /* @__PURE__ */ jsxs10("div", { ref, className: cn12("border-l-2 border-muted-foreground/30 pl-4", className), ...props, children: [
|
|
1226
1309
|
collapsible ? /* @__PURE__ */ jsxs10(
|
|
@@ -1231,7 +1314,7 @@ var Reasoning = React12.forwardRef(
|
|
|
1231
1314
|
"aria-expanded": isExpanded,
|
|
1232
1315
|
"aria-controls": contentId,
|
|
1233
1316
|
children: [
|
|
1234
|
-
/* @__PURE__ */ jsx12("span", { className: cn12("transition-transform", isExpanded ? "rotate-90" : ""), children: "
|
|
1317
|
+
/* @__PURE__ */ jsx12("span", { className: cn12("transition-transform", isExpanded ? "rotate-90" : ""), children: "?" }),
|
|
1235
1318
|
/* @__PURE__ */ jsx12("span", { children: headerText }),
|
|
1236
1319
|
isStreaming && /* @__PURE__ */ jsx12("span", { className: "flex gap-0.5", "aria-hidden": "true", children: [0, 150, 300].map((delay) => /* @__PURE__ */ jsx12(
|
|
1237
1320
|
"span",
|
|
@@ -1247,12 +1330,9 @@ var Reasoning = React12.forwardRef(
|
|
|
1247
1330
|
(isExpanded || !collapsible) && /* @__PURE__ */ jsx12("div", { id: contentId, className: "mt-3 space-y-3", children: steps.map((step, index) => /* @__PURE__ */ jsxs10("div", { className: "flex gap-3", children: [
|
|
1248
1331
|
/* @__PURE__ */ jsx12("div", { className: "w-3 h-3 rounded-full bg-primary/20 border-2 border-primary flex-shrink-0 mt-1" }),
|
|
1249
1332
|
/* @__PURE__ */ jsxs10("div", { className: "text-sm flex-1", children: [
|
|
1250
|
-
/* @__PURE__ */
|
|
1251
|
-
"Step ",
|
|
1252
|
-
index + 1
|
|
1253
|
-
] }),
|
|
1333
|
+
/* @__PURE__ */ jsx12("div", { className: "font-medium text-foreground mb-1", children: labels?.step?.(index + 1) ?? `Step ${index + 1}` }),
|
|
1254
1334
|
/* @__PURE__ */ jsx12("div", { className: "text-muted-foreground", children: step.content }),
|
|
1255
|
-
step.timestamp && /* @__PURE__ */ jsx12("div", { className: "text-xs text-muted-foreground mt-1", children: new Date(step.timestamp).toLocaleTimeString() })
|
|
1335
|
+
step.timestamp && /* @__PURE__ */ jsx12("div", { className: "text-xs text-muted-foreground mt-1", children: formatTime ? formatTime(new Date(step.timestamp)) : new Date(step.timestamp).toLocaleTimeString(locale) })
|
|
1256
1336
|
] })
|
|
1257
1337
|
] }, step.id)) })
|
|
1258
1338
|
] });
|
|
@@ -1265,19 +1345,19 @@ import * as React13 from "react";
|
|
|
1265
1345
|
import { cn as cn13 } from "@slipstream-ui/core";
|
|
1266
1346
|
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1267
1347
|
var statusChipClasses2 = {
|
|
1268
|
-
pending: "bg-warning/10 text-warning border-warning/20",
|
|
1269
|
-
running: "bg-info/10 text-info border-info/20",
|
|
1348
|
+
pending: "bg-warning/10 text-warning-ink border-warning/20",
|
|
1349
|
+
running: "bg-info/10 text-info-ink border-info/20",
|
|
1270
1350
|
completed: "bg-success/10 text-success border-success/20",
|
|
1271
1351
|
failed: "bg-destructive/10 text-destructive border-destructive/20"
|
|
1272
1352
|
};
|
|
1273
|
-
var
|
|
1353
|
+
var defaultStatusLabels = {
|
|
1274
1354
|
pending: "Pending",
|
|
1275
1355
|
running: "Running",
|
|
1276
1356
|
completed: "Completed",
|
|
1277
1357
|
failed: "Failed"
|
|
1278
1358
|
};
|
|
1279
1359
|
var ToolCall = React13.forwardRef(
|
|
1280
|
-
({ toolCall, className, showResult = true, ...props }, ref) => {
|
|
1360
|
+
({ toolCall, className, showResult = true, labels, ...props }, ref) => {
|
|
1281
1361
|
const serializedArguments = React13.useMemo(
|
|
1282
1362
|
() => JSON.stringify(toolCall.arguments, null, 2),
|
|
1283
1363
|
[toolCall.arguments]
|
|
@@ -1286,6 +1366,12 @@ var ToolCall = React13.forwardRef(
|
|
|
1286
1366
|
if (toolCall.result === void 0) return void 0;
|
|
1287
1367
|
return typeof toolCall.result === "string" ? toolCall.result : JSON.stringify(toolCall.result, null, 2);
|
|
1288
1368
|
}, [toolCall.result]);
|
|
1369
|
+
const statusLabels = {
|
|
1370
|
+
pending: labels?.pending ?? defaultStatusLabels.pending,
|
|
1371
|
+
running: labels?.running ?? defaultStatusLabels.running,
|
|
1372
|
+
completed: labels?.completed ?? defaultStatusLabels.completed,
|
|
1373
|
+
failed: labels?.failed ?? defaultStatusLabels.failed
|
|
1374
|
+
};
|
|
1289
1375
|
return /* @__PURE__ */ jsxs11(
|
|
1290
1376
|
"div",
|
|
1291
1377
|
{
|
|
@@ -1314,15 +1400,15 @@ var ToolCall = React13.forwardRef(
|
|
|
1314
1400
|
] }),
|
|
1315
1401
|
/* @__PURE__ */ jsxs11("div", { className: "space-y-2", children: [
|
|
1316
1402
|
/* @__PURE__ */ jsxs11("div", { children: [
|
|
1317
|
-
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Arguments" }),
|
|
1403
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: labels?.arguments ?? "Arguments" }),
|
|
1318
1404
|
/* @__PURE__ */ jsx13("pre", { className: "text-xs bg-muted p-2 rounded overflow-x-auto", children: /* @__PURE__ */ jsx13("code", { children: serializedArguments }) })
|
|
1319
1405
|
] }),
|
|
1320
1406
|
showResult && serializedResult !== void 0 && /* @__PURE__ */ jsxs11("div", { children: [
|
|
1321
|
-
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Result" }),
|
|
1407
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-muted-foreground mb-1", children: labels?.result ?? "Result" }),
|
|
1322
1408
|
/* @__PURE__ */ jsx13("pre", { className: "text-xs bg-muted p-2 rounded overflow-x-auto", children: /* @__PURE__ */ jsx13("code", { children: serializedResult }) })
|
|
1323
1409
|
] }),
|
|
1324
1410
|
toolCall.status === "failed" && toolCall.error && /* @__PURE__ */ jsxs11("div", { role: "alert", children: [
|
|
1325
|
-
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-destructive mb-1", children: "Error" }),
|
|
1411
|
+
/* @__PURE__ */ jsx13("div", { className: "text-xs font-medium text-destructive mb-1", children: labels?.error ?? "Error" }),
|
|
1326
1412
|
/* @__PURE__ */ jsx13("pre", { className: "text-xs bg-destructive/10 text-destructive p-2 rounded overflow-x-auto whitespace-pre-wrap", children: /* @__PURE__ */ jsx13("code", { children: toolCall.error }) })
|
|
1327
1413
|
] })
|
|
1328
1414
|
] })
|
|
@@ -1482,27 +1568,55 @@ StreamingIndicator.displayName = "StreamingIndicator";
|
|
|
1482
1568
|
// src/components/command-palette/CommandPalette.tsx
|
|
1483
1569
|
import * as React19 from "react";
|
|
1484
1570
|
import { cn as cn19 } from "@slipstream-ui/core";
|
|
1485
|
-
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1571
|
+
import { Fragment as Fragment5, jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1486
1572
|
function CommandPalette({
|
|
1487
1573
|
open,
|
|
1488
1574
|
onOpenChange,
|
|
1489
1575
|
commands,
|
|
1490
1576
|
onSelect,
|
|
1491
|
-
|
|
1577
|
+
loadCommands,
|
|
1578
|
+
debounceMs = 200,
|
|
1579
|
+
renderCommand,
|
|
1580
|
+
loadingText = "Searching\u2026",
|
|
1581
|
+
placeholder = "Type a command.",
|
|
1582
|
+
dialogLabel = "Command palette",
|
|
1583
|
+
listLabel = "Commands",
|
|
1584
|
+
emptyText = "No matching commands."
|
|
1492
1585
|
}) {
|
|
1493
1586
|
const [query, setQuery] = React19.useState("");
|
|
1494
1587
|
const [activeIndex, setActiveIndex] = React19.useState(0);
|
|
1588
|
+
const [asyncCommands, setAsyncCommands] = React19.useState([]);
|
|
1589
|
+
const [loading, setLoading] = React19.useState(false);
|
|
1590
|
+
const requestId = React19.useRef(0);
|
|
1591
|
+
const asyncSignature = loadCommands ? String(loadCommands.length) : "";
|
|
1495
1592
|
const inputRef = React19.useRef(null);
|
|
1496
1593
|
const listboxId = React19.useId();
|
|
1497
1594
|
const optionId = (index) => `${listboxId}-option-${index}`;
|
|
1595
|
+
React19.useEffect(() => {
|
|
1596
|
+
if (!open || !loadCommands) return;
|
|
1597
|
+
const id = ++requestId.current;
|
|
1598
|
+
setLoading(true);
|
|
1599
|
+
const timer = setTimeout(async () => {
|
|
1600
|
+
try {
|
|
1601
|
+
const result = await loadCommands(query);
|
|
1602
|
+
if (requestId.current === id) setAsyncCommands(result);
|
|
1603
|
+
} catch {
|
|
1604
|
+
if (requestId.current === id) setAsyncCommands([]);
|
|
1605
|
+
} finally {
|
|
1606
|
+
if (requestId.current === id) setLoading(false);
|
|
1607
|
+
}
|
|
1608
|
+
}, debounceMs);
|
|
1609
|
+
return () => clearTimeout(timer);
|
|
1610
|
+
}, [open, query, debounceMs, asyncSignature]);
|
|
1498
1611
|
const filtered = React19.useMemo(() => {
|
|
1612
|
+
if (loadCommands) return asyncCommands;
|
|
1499
1613
|
const terms = query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
1500
1614
|
if (terms.length === 0) return commands;
|
|
1501
1615
|
return commands.filter((command) => {
|
|
1502
1616
|
const haystack = `${command.label} ${command.section ?? ""} ${(command.keywords ?? []).join(" ")}`.toLowerCase();
|
|
1503
1617
|
return terms.every((term) => haystack.includes(term));
|
|
1504
1618
|
});
|
|
1505
|
-
}, [commands, query]);
|
|
1619
|
+
}, [commands, query, asyncCommands, loadCommands]);
|
|
1506
1620
|
React19.useEffect(() => {
|
|
1507
1621
|
if (open) {
|
|
1508
1622
|
setQuery("");
|
|
@@ -1554,7 +1668,7 @@ function CommandPalette({
|
|
|
1554
1668
|
"aria-controls": listboxId,
|
|
1555
1669
|
"aria-activedescendant": filtered.length > 0 ? optionId(activeIndex) : void 0,
|
|
1556
1670
|
"aria-autocomplete": "list",
|
|
1557
|
-
"aria-label":
|
|
1671
|
+
"aria-label": dialogLabel,
|
|
1558
1672
|
placeholder,
|
|
1559
1673
|
value: query,
|
|
1560
1674
|
onChange: (event) => {
|
|
@@ -1565,37 +1679,54 @@ function CommandPalette({
|
|
|
1565
1679
|
className: "w-full border-b border-border bg-transparent px-4 py-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring placeholder:text-muted-foreground"
|
|
1566
1680
|
}
|
|
1567
1681
|
),
|
|
1568
|
-
/* @__PURE__ */ jsxs16(
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1682
|
+
/* @__PURE__ */ jsxs16(
|
|
1683
|
+
"ul",
|
|
1684
|
+
{
|
|
1685
|
+
id: listboxId,
|
|
1686
|
+
role: "listbox",
|
|
1687
|
+
"aria-label": listLabel,
|
|
1688
|
+
"aria-busy": loading || void 0,
|
|
1689
|
+
className: "max-h-72 overflow-y-auto py-1",
|
|
1690
|
+
children: [
|
|
1691
|
+
loading && filtered.length === 0 && /* @__PURE__ */ jsx19("li", { role: "presentation", className: "px-4 py-3 text-sm text-muted-foreground", children: loadingText }),
|
|
1692
|
+
!loading && filtered.length === 0 && /* @__PURE__ */ jsx19("li", { role: "presentation", className: "px-4 py-3 text-sm text-muted-foreground", children: emptyText }),
|
|
1693
|
+
filtered.map((command, index) => {
|
|
1694
|
+
const showSection = command.section && command.section !== lastSection;
|
|
1695
|
+
lastSection = command.section ?? lastSection;
|
|
1696
|
+
return /* @__PURE__ */ jsxs16(React19.Fragment, { children: [
|
|
1697
|
+
showSection && /* @__PURE__ */ jsx19("li", { role: "presentation", className: "px-4 pb-1 pt-3 text-xs font-medium uppercase text-muted-foreground", children: command.section }),
|
|
1698
|
+
/* @__PURE__ */ jsx19(
|
|
1699
|
+
"li",
|
|
1700
|
+
{
|
|
1701
|
+
id: optionId(index),
|
|
1702
|
+
role: "option",
|
|
1703
|
+
"aria-selected": index === activeIndex,
|
|
1704
|
+
onMouseEnter: () => setActiveIndex(index),
|
|
1705
|
+
onClick: () => {
|
|
1706
|
+
onSelect(command);
|
|
1707
|
+
onOpenChange(false);
|
|
1708
|
+
},
|
|
1709
|
+
className: cn19(
|
|
1710
|
+
"flex cursor-pointer items-center justify-between px-4 py-2 text-sm",
|
|
1711
|
+
index === activeIndex ? "bg-primary/10 text-foreground" : "text-muted-foreground"
|
|
1712
|
+
),
|
|
1713
|
+
children: renderCommand ? renderCommand(command, { active: index === activeIndex }) : /* @__PURE__ */ jsxs16(Fragment5, { children: [
|
|
1714
|
+
/* @__PURE__ */ jsxs16("span", { className: "flex min-w-0 items-center gap-2", children: [
|
|
1715
|
+
command.icon && /* @__PURE__ */ jsx19("span", { className: "shrink-0 [&_svg]:size-4", children: command.icon }),
|
|
1716
|
+
/* @__PURE__ */ jsxs16("span", { className: "min-w-0", children: [
|
|
1717
|
+
/* @__PURE__ */ jsx19("span", { className: "block truncate", children: command.label }),
|
|
1718
|
+
command.description && /* @__PURE__ */ jsx19("span", { className: "block text-xs text-muted-foreground", children: command.description })
|
|
1719
|
+
] })
|
|
1720
|
+
] }),
|
|
1721
|
+
command.shortcut && /* @__PURE__ */ jsx19("span", { className: "font-mono text-xs", children: command.shortcut })
|
|
1722
|
+
] })
|
|
1723
|
+
}
|
|
1724
|
+
)
|
|
1725
|
+
] }, command.id);
|
|
1726
|
+
})
|
|
1727
|
+
]
|
|
1728
|
+
}
|
|
1729
|
+
)
|
|
1599
1730
|
] })
|
|
1600
1731
|
}
|
|
1601
1732
|
);
|