@ciridae/ui-agent 0.3.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.
Files changed (70) hide show
  1. package/README.md +19 -0
  2. package/dist/components/agentic/agent-plan.d.ts +27 -0
  3. package/dist/components/agentic/agent-plan.js +43 -0
  4. package/dist/components/agentic/agent-queue.d.ts +46 -0
  5. package/dist/components/agentic/agent-queue.js +53 -0
  6. package/dist/components/agentic/agent-task.d.ts +16 -0
  7. package/dist/components/agentic/agent-task.js +20 -0
  8. package/dist/components/agentic/approval-request.d.ts +24 -0
  9. package/dist/components/agentic/approval-request.js +57 -0
  10. package/dist/components/agentic/artifact.d.ts +24 -0
  11. package/dist/components/agentic/artifact.js +147 -0
  12. package/dist/components/agentic/attachments.d.ts +124 -0
  13. package/dist/components/agentic/attachments.js +591 -0
  14. package/dist/components/agentic/clipboard.d.ts +2 -0
  15. package/dist/components/agentic/clipboard.js +12 -0
  16. package/dist/components/agentic/code-block.d.ts +44 -0
  17. package/dist/components/agentic/code-block.js +182 -0
  18. package/dist/components/agentic/conversation.d.ts +25 -0
  19. package/dist/components/agentic/conversation.js +56 -0
  20. package/dist/components/agentic/file-tree.d.ts +24 -0
  21. package/dist/components/agentic/file-tree.js +56 -0
  22. package/dist/components/agentic/image.d.ts +9 -0
  23. package/dist/components/agentic/image.js +11 -0
  24. package/dist/components/agentic/inline-citation.d.ts +40 -0
  25. package/dist/components/agentic/inline-citation.js +111 -0
  26. package/dist/components/agentic/message-branch.d.ts +20 -0
  27. package/dist/components/agentic/message-branch.js +83 -0
  28. package/dist/components/agentic/message-response.css +242 -0
  29. package/dist/components/agentic/message-response.css.d.ts +2 -0
  30. package/dist/components/agentic/message.d.ts +29 -0
  31. package/dist/components/agentic/message.js +191 -0
  32. package/dist/components/agentic/model-selector.d.ts +39 -0
  33. package/dist/components/agentic/model-selector.js +47 -0
  34. package/dist/components/agentic/prompt-input-action-menu.d.ts +16 -0
  35. package/dist/components/agentic/prompt-input-action-menu.js +22 -0
  36. package/dist/components/agentic/prompt-input-command.d.ts +18 -0
  37. package/dist/components/agentic/prompt-input-command.js +25 -0
  38. package/dist/components/agentic/prompt-input-hover-card.d.ts +10 -0
  39. package/dist/components/agentic/prompt-input-hover-card.js +13 -0
  40. package/dist/components/agentic/prompt-input-select.d.ts +14 -0
  41. package/dist/components/agentic/prompt-input-select.js +19 -0
  42. package/dist/components/agentic/prompt-input-tabs.d.ts +17 -0
  43. package/dist/components/agentic/prompt-input-tabs.js +45 -0
  44. package/dist/components/agentic/prompt-input.d.ts +66 -0
  45. package/dist/components/agentic/prompt-input.js +227 -0
  46. package/dist/components/agentic/reasoning.d.ts +21 -0
  47. package/dist/components/agentic/reasoning.js +106 -0
  48. package/dist/components/agentic/run-checkpoint.d.ts +13 -0
  49. package/dist/components/agentic/run-checkpoint.js +19 -0
  50. package/dist/components/agentic/run-trace.d.ts +30 -0
  51. package/dist/components/agentic/run-trace.js +56 -0
  52. package/dist/components/agentic/sandbox.d.ts +24 -0
  53. package/dist/components/agentic/sandbox.js +33 -0
  54. package/dist/components/agentic/schema-display.d.ts +39 -0
  55. package/dist/components/agentic/schema-display.js +56 -0
  56. package/dist/components/agentic/shimmer.d.ts +11 -0
  57. package/dist/components/agentic/shimmer.js +16 -0
  58. package/dist/components/agentic/snippet.d.ts +18 -0
  59. package/dist/components/agentic/snippet.js +35 -0
  60. package/dist/components/agentic/sources.d.ts +16 -0
  61. package/dist/components/agentic/sources.js +130 -0
  62. package/dist/components/agentic/terminal.d.ts +24 -0
  63. package/dist/components/agentic/terminal.js +47 -0
  64. package/dist/components/agentic/tool.d.ts +25 -0
  65. package/dist/components/agentic/tool.js +73 -0
  66. package/dist/components/agentic/types.d.ts +172 -0
  67. package/dist/components/agentic/types.js +1 -0
  68. package/dist/components/agentic/web-preview.d.ts +25 -0
  69. package/dist/components/agentic/web-preview.js +33 -0
  70. package/package.json +179 -0
@@ -0,0 +1,14 @@
1
+ import type * as React from "react";
2
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ciridae/ui/select";
3
+ type PromptInputSelectProps = React.ComponentProps<typeof Select>;
4
+ type PromptInputSelectTriggerProps = React.ComponentProps<typeof SelectTrigger>;
5
+ type PromptInputSelectContentProps = React.ComponentProps<typeof SelectContent>;
6
+ type PromptInputSelectItemProps = React.ComponentProps<typeof SelectItem>;
7
+ type PromptInputSelectValueProps = React.ComponentProps<typeof SelectValue>;
8
+ declare function PromptInputSelect(props: PromptInputSelectProps): React.JSX.Element;
9
+ declare function PromptInputSelectTrigger({ className, size, ...props }: PromptInputSelectTriggerProps): React.JSX.Element;
10
+ declare function PromptInputSelectContent({ align, className, ...props }: PromptInputSelectContentProps): React.JSX.Element;
11
+ declare function PromptInputSelectItem({ className, ...props }: PromptInputSelectItemProps): React.JSX.Element;
12
+ declare function PromptInputSelectValue(props: PromptInputSelectValueProps): React.JSX.Element;
13
+ export { PromptInputSelect, PromptInputSelectContent, PromptInputSelectItem, PromptInputSelectTrigger, PromptInputSelectValue, };
14
+ export type { PromptInputSelectContentProps, PromptInputSelectItemProps, PromptInputSelectProps, PromptInputSelectTriggerProps, PromptInputSelectValueProps, };
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@ciridae/ui/select";
3
+ import { cn } from "@ciridae/ui/utils";
4
+ function PromptInputSelect(props) {
5
+ return _jsx(Select, { ...props });
6
+ }
7
+ function PromptInputSelectTrigger({ className, size = "sm", ...props }) {
8
+ return (_jsx(SelectTrigger, { "data-slot": "prompt-input-select-trigger", size: size, className: cn("h-(--control-height-sm) min-w-0 border-transparent bg-transparent px-2 shadow-none hover:bg-accent hover:text-accent-foreground dark:bg-transparent dark:hover:bg-accent/50 [&_[data-slot=select-value]>svg:not([class*='size-'])]:size-3.5", className), ...props }));
9
+ }
10
+ function PromptInputSelectContent({ align = "start", className, ...props }) {
11
+ return (_jsx(SelectContent, { "data-slot": "prompt-input-select-content", align: align, className: cn("min-w-52", className), ...props }));
12
+ }
13
+ function PromptInputSelectItem({ className, ...props }) {
14
+ return (_jsx(SelectItem, { "data-slot": "prompt-input-select-item", className: cn("gap-2", className), ...props }));
15
+ }
16
+ function PromptInputSelectValue(props) {
17
+ return _jsx(SelectValue, { "data-slot": "prompt-input-select-value", ...props });
18
+ }
19
+ export { PromptInputSelect, PromptInputSelectContent, PromptInputSelectItem, PromptInputSelectTrigger, PromptInputSelectValue, };
@@ -0,0 +1,17 @@
1
+ import * as React from "react";
2
+ import { Tabs, TabsContent, TabsTrigger } from "@ciridae/ui/tabs";
3
+ type PromptInputTabsListProps = React.ComponentProps<typeof Tabs>;
4
+ type PromptInputTabProps = React.ComponentProps<typeof TabsTrigger>;
5
+ type PromptInputTabLabelProps = React.ComponentProps<"span">;
6
+ type PromptInputTabBodyProps = React.ComponentProps<typeof TabsContent>;
7
+ type PromptInputTabItemProps = React.ComponentProps<"div">;
8
+ declare function PromptInputTabsList({ children, className, orientation, ...props }: PromptInputTabsListProps): React.JSX.Element;
9
+ declare function PromptInputTab({ className, ...props }: PromptInputTabProps): React.JSX.Element;
10
+ declare namespace PromptInputTab {
11
+ var displayName: string;
12
+ }
13
+ declare function PromptInputTabLabel({ className, ...props }: PromptInputTabLabelProps): React.JSX.Element;
14
+ declare function PromptInputTabBody({ className, ...props }: PromptInputTabBodyProps): React.JSX.Element;
15
+ declare function PromptInputTabItem({ className, ...props }: PromptInputTabItemProps): React.JSX.Element;
16
+ export { PromptInputTab, PromptInputTabBody, PromptInputTabItem, PromptInputTabLabel, PromptInputTabsList, };
17
+ export type { PromptInputTabBodyProps, PromptInputTabItemProps, PromptInputTabLabelProps, PromptInputTabProps, PromptInputTabsListProps, };
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@ciridae/ui/tabs";
4
+ import { cn } from "@ciridae/ui/utils";
5
+ function PromptInputTabsList({ children, className, orientation = "horizontal", ...props }) {
6
+ const childrenArray = React.Children.toArray(children);
7
+ const tabs = childrenArray.filter(isPromptInputTabElement);
8
+ const bodies = childrenArray.filter((child) => !isPromptInputTabElement(child));
9
+ return (_jsxs(Tabs, { "data-slot": "prompt-input-tabs-list", orientation: orientation, className: cn("gap-2 rounded-md border bg-background p-1", "data-[orientation=horizontal]:flex-col data-[orientation=vertical]:flex-row", className), ...props, children: [_jsx(TabsList, { variant: "default", className: "h-auto min-w-0 justify-start gap-1 bg-transparent p-0", children: tabs }), bodies] }));
10
+ }
11
+ function PromptInputTab({ className, ...props }) {
12
+ return (_jsx(TabsTrigger, { "data-slot": "prompt-input-tab", className: cn("h-(--control-height-sm) flex-none gap-1.5 rounded-sm px-2 text-xs", className), ...props }));
13
+ }
14
+ function PromptInputTabLabel({ className, ...props }) {
15
+ return (_jsx("span", { "data-slot": "prompt-input-tab-label", className: cn("min-w-0 truncate", className), ...props }));
16
+ }
17
+ function PromptInputTabBody({ className, ...props }) {
18
+ return (_jsx(TabsContent, { "data-slot": "prompt-input-tab-body", className: cn("mt-0 rounded-sm p-2 text-sm", className), ...props }));
19
+ }
20
+ function PromptInputTabItem({ className, ...props }) {
21
+ return (_jsx("div", { "data-slot": "prompt-input-tab-item", className: cn("flex min-w-0 items-start gap-2 rounded-sm px-2 py-1.5 text-sm text-foreground", "[&_svg]:mt-0.5 [&_svg]:size-4 [&_svg]:shrink-0 [&_svg]:text-muted-foreground", className), ...props }));
22
+ }
23
+ function isPromptInputTabElement(child) {
24
+ if (!React.isValidElement(child))
25
+ return false;
26
+ return getPromptInputTabTypeName(child.type) === "PromptInputTab";
27
+ }
28
+ function getPromptInputTabTypeName(type) {
29
+ if (typeof type === "function") {
30
+ if ("displayName" in type && typeof type.displayName === "string")
31
+ return type.displayName;
32
+ return type.name;
33
+ }
34
+ if (typeof type !== "object" || type === null)
35
+ return undefined;
36
+ if ("displayName" in type && typeof type.displayName === "string")
37
+ return type.displayName;
38
+ if ("type" in type)
39
+ return getPromptInputTabTypeName(type.type);
40
+ if ("render" in type)
41
+ return getPromptInputTabTypeName(type.render);
42
+ return undefined;
43
+ }
44
+ PromptInputTab.displayName = "PromptInputTab";
45
+ export { PromptInputTab, PromptInputTabBody, PromptInputTabItem, PromptInputTabLabel, PromptInputTabsList, };
@@ -0,0 +1,66 @@
1
+ import * as React from "react";
2
+ export { AttachmentActionAddFiles as PromptInputActionAddAttachments, AttachmentActionAddScreenshot as PromptInputActionAddScreenshot, } from "@ciridae/ui-agent/attachments";
3
+ export type { AttachmentActionAddFilesProps as PromptInputActionAddAttachmentsProps, AttachmentActionAddScreenshotProps as PromptInputActionAddScreenshotProps, } from "@ciridae/ui-agent/attachments";
4
+ export * from "@ciridae/ui-agent/prompt-input-action-menu";
5
+ export * from "@ciridae/ui-agent/prompt-input-command";
6
+ export * from "@ciridae/ui-agent/prompt-input-hover-card";
7
+ export * from "@ciridae/ui-agent/prompt-input-select";
8
+ export * from "@ciridae/ui-agent/prompt-input-tabs";
9
+ import { type AgenticAttachment, type AttachmentProviderProps } from "@ciridae/ui-agent/attachments";
10
+ import type { AgenticChatStatus } from "@ciridae/ui-agent/types";
11
+ import { Button } from "@ciridae/ui/button";
12
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupTextarea } from "@ciridae/ui/input-group";
13
+ type PromptInputMessage = {
14
+ attachments: AgenticAttachment[];
15
+ text: string;
16
+ };
17
+ type PromptInputTextContextValue = {
18
+ clear: () => void;
19
+ setValue: (value: string) => void;
20
+ value: string;
21
+ };
22
+ type PromptInputProviderContextValue = {
23
+ text: PromptInputTextContextValue;
24
+ };
25
+ type PromptInputProviderProps = AttachmentProviderProps & {
26
+ defaultValue?: string;
27
+ onValueChange?: (value: string) => void;
28
+ value?: string;
29
+ };
30
+ type PromptInputProps = Omit<React.ComponentProps<"form">, "onError" | "onSubmit"> & Pick<AttachmentProviderProps, "accept" | "maxAttachmentSizeMb" | "maxAttachments" | "multiple" | "onAttachmentError" | "onCaptureScreenshot"> & {
31
+ disabled?: boolean;
32
+ globalDrop?: boolean;
33
+ onSubmit?: (message: PromptInputMessage) => void | Promise<void>;
34
+ status?: AgenticChatStatus;
35
+ };
36
+ type PromptInputBodyProps = React.ComponentProps<typeof InputGroup>;
37
+ type PromptInputTextareaProps = Omit<React.ComponentProps<typeof InputGroupTextarea>, "onChange"> & {
38
+ onValueChange?: (value: string) => void;
39
+ value?: string;
40
+ };
41
+ type PromptInputHeaderProps = React.ComponentProps<"div">;
42
+ type PromptInputFooterProps = React.ComponentProps<"div">;
43
+ type PromptInputToolsProps = React.ComponentProps<typeof InputGroupAddon>;
44
+ type PromptInputButtonProps = React.ComponentProps<typeof InputGroupButton> & {
45
+ label?: string;
46
+ tooltip?: string;
47
+ };
48
+ type PromptInputSubmitProps = React.ComponentProps<typeof Button> & {
49
+ label?: string;
50
+ onStop?: () => void;
51
+ status?: AgenticChatStatus;
52
+ stopLabel?: string;
53
+ };
54
+ declare function PromptInputProvider({ children, defaultValue, onValueChange, value, ...attachmentProviderProps }: PromptInputProviderProps): React.JSX.Element;
55
+ declare function usePromptInputProvider(): PromptInputProviderContextValue;
56
+ declare function useOptionalPromptInputProvider(): PromptInputProviderContextValue | null;
57
+ declare function PromptInput(props: PromptInputProps): React.JSX.Element;
58
+ declare function PromptInputBody({ className, ...props }: PromptInputBodyProps): React.JSX.Element;
59
+ declare function PromptInputTextarea({ className, disabled, onKeyDown, onPaste, onValueChange, value, ...props }: PromptInputTextareaProps): React.JSX.Element;
60
+ declare function PromptInputHeader({ className, ...props }: PromptInputHeaderProps): React.JSX.Element;
61
+ declare function PromptInputFooter({ className, ...props }: PromptInputFooterProps): React.JSX.Element;
62
+ declare function PromptInputTools({ align, className, ...props }: PromptInputToolsProps): React.JSX.Element;
63
+ declare function PromptInputButton({ children, className, label, size, tooltip, variant, ...props }: PromptInputButtonProps): React.JSX.Element;
64
+ declare function PromptInputSubmit({ children, className, disabled, label, onClick, onStop, size, status, stopLabel, type, variant, ...props }: PromptInputSubmitProps): React.JSX.Element;
65
+ export { PromptInput, PromptInputBody, PromptInputButton, PromptInputFooter, PromptInputHeader, PromptInputProvider, PromptInputSubmit, PromptInputTextarea, PromptInputTools, useOptionalPromptInputProvider, usePromptInputProvider, };
66
+ export type { PromptInputBodyProps, PromptInputButtonProps, PromptInputFooterProps, PromptInputHeaderProps, PromptInputMessage, PromptInputProps, PromptInputProviderContextValue, PromptInputProviderProps, PromptInputSubmitProps, PromptInputTextareaProps, PromptInputTextContextValue, PromptInputToolsProps, };
@@ -0,0 +1,227 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable max-lines, react-refresh/only-export-components */
3
+ import { ArrowUpIcon, SquareIcon } from "lucide-react";
4
+ import * as React from "react";
5
+ export { AttachmentActionAddFiles as PromptInputActionAddAttachments, AttachmentActionAddScreenshot as PromptInputActionAddScreenshot, } from "@ciridae/ui-agent/attachments";
6
+ export * from "@ciridae/ui-agent/prompt-input-action-menu";
7
+ export * from "@ciridae/ui-agent/prompt-input-command";
8
+ export * from "@ciridae/ui-agent/prompt-input-hover-card";
9
+ export * from "@ciridae/ui-agent/prompt-input-select";
10
+ export * from "@ciridae/ui-agent/prompt-input-tabs";
11
+ import { AttachmentProvider, prepareAttachmentsForSubmit, useAttachmentDropTarget, useAttachments, useOptionalAttachments, } from "@ciridae/ui-agent/attachments";
12
+ import { Button } from "@ciridae/ui/button";
13
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupTextarea, } from "@ciridae/ui/input-group";
14
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@ciridae/ui/tooltip";
15
+ import { cn } from "@ciridae/ui/utils";
16
+ import { css } from "@ciridae/ui/styled-system/css";
17
+ const PromptInputProviderContext = React.createContext(null);
18
+ const PromptInputContext = React.createContext({
19
+ status: "idle",
20
+ });
21
+ const promptInputClassName = css({
22
+ backgroundColor: "background",
23
+ borderColor: "border",
24
+ borderRadius: "lg",
25
+ borderStyle: "solid",
26
+ borderWidth: "default",
27
+ boxShadow: "xs",
28
+ display: "grid",
29
+ gap: "gap.2",
30
+ outline: "none",
31
+ padding: "spacing.2",
32
+ transitionProperty: "color, box-shadow",
33
+ width: "full",
34
+ "&:focus-within": {
35
+ borderColor: "ring",
36
+ boxShadow: "focus",
37
+ },
38
+ "&[data-disabled='true']": {
39
+ opacity: 0.6,
40
+ },
41
+ });
42
+ const promptInputBodyClassName = css({
43
+ alignItems: "stretch",
44
+ backgroundColor: "transparent",
45
+ borderWidth: 0,
46
+ boxShadow: "none",
47
+ minHeight: "6rem",
48
+ _dark: {
49
+ backgroundColor: "transparent",
50
+ },
51
+ });
52
+ const promptInputTextareaClassName = css({
53
+ fontSize: "sm",
54
+ lineHeight: "relaxed",
55
+ minHeight: "6rem",
56
+ paddingBlock: "spacing.2",
57
+ paddingInline: "spacing.2",
58
+ "&::placeholder": {
59
+ color: "muted.foreground/70",
60
+ },
61
+ });
62
+ function PromptInputProvider({ children, defaultValue = "", onValueChange, value, ...attachmentProviderProps }) {
63
+ const [localValue, setLocalValue] = React.useState(defaultValue);
64
+ const resolvedValue = value ?? localValue;
65
+ const setValue = React.useCallback((nextValue) => {
66
+ if (value === undefined)
67
+ setLocalValue(nextValue);
68
+ onValueChange?.(nextValue);
69
+ }, [onValueChange, value]);
70
+ const clear = React.useCallback(() => setValue(""), [setValue]);
71
+ const contextValue = React.useMemo(() => ({
72
+ text: {
73
+ clear,
74
+ setValue,
75
+ value: resolvedValue,
76
+ },
77
+ }), [clear, resolvedValue, setValue]);
78
+ return (_jsx(AttachmentProvider, { ...attachmentProviderProps, children: _jsx(PromptInputProviderContext.Provider, { value: contextValue, children: children }) }));
79
+ }
80
+ function usePromptInputProvider() {
81
+ const context = React.useContext(PromptInputProviderContext);
82
+ if (!context) {
83
+ throw new Error("usePromptInputProvider must be used within PromptInputProvider.");
84
+ }
85
+ return context;
86
+ }
87
+ function useOptionalPromptInputProvider() {
88
+ return React.useContext(PromptInputProviderContext);
89
+ }
90
+ function PromptInput(props) {
91
+ const { accept, children, maxAttachmentSizeMb, maxAttachments, multiple, onAttachmentError, onCaptureScreenshot, ...innerProps } = props;
92
+ const existingAttachments = useOptionalAttachments();
93
+ if (existingAttachments)
94
+ return _jsx(PromptInputInner, { ...innerProps, children: children });
95
+ return (_jsx(AttachmentProvider, { accept: accept, maxAttachmentSizeMb: maxAttachmentSizeMb, maxAttachments: maxAttachments, multiple: multiple, onAttachmentError: onAttachmentError, onCaptureScreenshot: onCaptureScreenshot, children: _jsx(PromptInputInner, { ...innerProps, children: children }) }));
96
+ }
97
+ function PromptInputInner({ children, className, disabled, globalDrop, onSubmit, status = "idle", ...props }) {
98
+ const contextValue = React.useMemo(() => ({ disabled, status }), [disabled, status]);
99
+ const formRef = React.useRef(null);
100
+ const attachments = useAttachments();
101
+ const provider = useOptionalPromptInputProvider();
102
+ useAttachmentDropTarget({ global: globalDrop, ref: formRef });
103
+ const handleSubmit = React.useCallback(async (event) => {
104
+ event.preventDefault();
105
+ if (!onSubmit)
106
+ return;
107
+ const form = event.currentTarget;
108
+ const text = getPromptInputFormText(form, provider?.text.value);
109
+ const submitAttachments = await prepareAttachmentsForSubmit(attachments.files);
110
+ try {
111
+ await onSubmit({ attachments: submitAttachments, text });
112
+ attachments.clear();
113
+ if (provider)
114
+ provider.text.clear();
115
+ else
116
+ form.reset();
117
+ }
118
+ catch {
119
+ // Keep composer state intact so hosts can show retry affordances.
120
+ }
121
+ }, [attachments, onSubmit, provider]);
122
+ return (_jsx(PromptInputContext.Provider, { value: contextValue, children: _jsx("form", { "data-disabled": disabled ? "true" : undefined, "data-slot": "prompt-input", "data-status": status, onSubmit: handleSubmit, ref: formRef, className: cn("group/prompt-input", promptInputClassName, className), ...props, children: children }) }));
123
+ }
124
+ function getPromptInputFormText(form, fallback = "") {
125
+ const textarea = form.querySelector('[data-slot="prompt-input-textarea"]');
126
+ if (textarea)
127
+ return textarea.value;
128
+ const formData = new FormData(form);
129
+ const message = formData.get("message");
130
+ return typeof message === "string" ? message : fallback;
131
+ }
132
+ function PromptInputBody({ className, ...props }) {
133
+ return (_jsx(InputGroup, { "data-slot": "prompt-input-body", className: cn(promptInputBodyClassName, className), ...props }));
134
+ }
135
+ function PromptInputTextarea({ className, disabled, onKeyDown, onPaste, onValueChange, value, ...props }) {
136
+ const context = React.useContext(PromptInputContext);
137
+ const provider = useOptionalPromptInputProvider();
138
+ const attachments = useAttachments();
139
+ const isDisabled = disabled ?? context.disabled;
140
+ const resolvedValue = value ?? provider?.text.value;
141
+ const handleKeyDown = React.useCallback((event) => {
142
+ onKeyDown?.(event);
143
+ if (event.defaultPrevented)
144
+ return;
145
+ if (event.key === "Backspace" &&
146
+ event.currentTarget.value === "" &&
147
+ attachments.files.length > 0) {
148
+ event.preventDefault();
149
+ const lastAttachment = attachments.files[attachments.files.length - 1];
150
+ if (lastAttachment)
151
+ attachments.remove(lastAttachment.id);
152
+ return;
153
+ }
154
+ if (event.key !== "Enter" || event.shiftKey)
155
+ return;
156
+ if (event.nativeEvent.isComposing)
157
+ return;
158
+ if (isStopStatus(context.status))
159
+ return;
160
+ event.preventDefault();
161
+ event.currentTarget.form?.requestSubmit();
162
+ }, [attachments, context.status, onKeyDown]);
163
+ const handlePaste = React.useCallback((event) => {
164
+ onPaste?.(event);
165
+ if (event.defaultPrevented)
166
+ return;
167
+ const files = Array.from(event.clipboardData.files);
168
+ if (files.length === 0)
169
+ return;
170
+ event.preventDefault();
171
+ attachments.add(files);
172
+ }, [attachments, onPaste]);
173
+ const handleChange = React.useCallback((event) => {
174
+ onValueChange?.(event.target.value);
175
+ if (value === undefined)
176
+ provider?.text.setValue(event.target.value);
177
+ }, [onValueChange, provider, value]);
178
+ return (_jsx(InputGroupTextarea, { ...props, "data-slot": "prompt-input-textarea", disabled: isDisabled, name: props.name ?? "message", value: resolvedValue, onChange: handleChange, onKeyDown: handleKeyDown, onPaste: handlePaste, className: cn(promptInputTextareaClassName, className) }));
179
+ }
180
+ function PromptInputHeader({ className, ...props }) {
181
+ return (_jsx("div", { "data-slot": "prompt-input-header", className: cn("flex min-w-0 items-center justify-between gap-2 px-1", className), ...props }));
182
+ }
183
+ function PromptInputFooter({ className, ...props }) {
184
+ return (_jsx("div", { "data-slot": "prompt-input-footer", className: cn("flex min-w-0 items-center justify-between gap-2 px-1", className), ...props }));
185
+ }
186
+ function PromptInputTools({ align = "block-end", className, ...props }) {
187
+ return (_jsx(InputGroupAddon, { align: align, "data-slot": "prompt-input-tools", className: cn("min-w-0 justify-between gap-2 px-0 pb-0", className), ...props }));
188
+ }
189
+ function PromptInputButton({ children, className, label, size = "icon-sm", tooltip, variant = "ghost", ...props }) {
190
+ const button = (_jsx(InputGroupButton, { "aria-label": label ?? tooltip, "data-slot": "prompt-input-button", size: size, variant: variant, className: cn("shrink-0 text-muted-foreground", className), ...props, children: children }));
191
+ if (!tooltip)
192
+ return button;
193
+ return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: button }), _jsx(TooltipContent, { children: tooltip })] }) }));
194
+ }
195
+ function PromptInputSubmit({ children, className, disabled, label = "Send message", onClick, onStop, size = "icon-sm", status, stopLabel = "Stop response", type, variant = "default", ...props }) {
196
+ const context = React.useContext(PromptInputContext);
197
+ const resolvedStatus = status ?? context.status;
198
+ const isStopping = isStopStatus(resolvedStatus);
199
+ const resolvedDisabled = disabled ?? context.disabled;
200
+ const handleClick = React.useCallback((event) => {
201
+ onClick?.(event);
202
+ if (event.defaultPrevented || !isStopping)
203
+ return;
204
+ event.preventDefault();
205
+ onStop?.();
206
+ }, [isStopping, onClick, onStop]);
207
+ return (_jsx(Button, { "aria-label": isStopping ? stopLabel : label, "data-slot": "prompt-input-submit", "data-status": resolvedStatus, disabled: resolvedDisabled, onClick: handleClick, size: size, type: getSubmitType(isStopping, type), variant: getSubmitVariant(isStopping, variant), className: cn("shrink-0", className), ...props, children: children ?? getSubmitIcon(isStopping) }));
208
+ }
209
+ function isStopStatus(status) {
210
+ return status === "submitted" || status === "streaming";
211
+ }
212
+ function getSubmitType(isStopping, type) {
213
+ if (isStopping)
214
+ return "button";
215
+ return type ?? "submit";
216
+ }
217
+ function getSubmitVariant(isStopping, variant) {
218
+ if (isStopping)
219
+ return "outline";
220
+ return variant;
221
+ }
222
+ function getSubmitIcon(isStopping) {
223
+ if (isStopping)
224
+ return _jsx(SquareIcon, {});
225
+ return _jsx(ArrowUpIcon, {});
226
+ }
227
+ export { PromptInput, PromptInputBody, PromptInputButton, PromptInputFooter, PromptInputHeader, PromptInputProvider, PromptInputSubmit, PromptInputTextarea, PromptInputTools, useOptionalPromptInputProvider, usePromptInputProvider, };
@@ -0,0 +1,21 @@
1
+ import type * as React from "react";
2
+ import "@ciridae/ui-agent/message-response.css";
3
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@ciridae/ui/collapsible";
4
+ type ReasoningProps = React.ComponentProps<typeof Collapsible> & {
5
+ defaultOpen?: boolean;
6
+ duration?: number;
7
+ isStreaming?: boolean;
8
+ onOpenChange?: (open: boolean) => void;
9
+ open?: boolean;
10
+ };
11
+ type ReasoningTriggerProps = React.ComponentProps<typeof CollapsibleTrigger> & {
12
+ getThinkingMessage?: (isStreaming: boolean, duration?: number) => React.ReactNode;
13
+ };
14
+ type ReasoningContentProps = React.ComponentProps<typeof CollapsibleContent> & {
15
+ children: string;
16
+ };
17
+ declare const Reasoning: React.MemoExoticComponent<({ children, className, defaultOpen, duration: durationProp, isStreaming, onOpenChange, open, ...props }: ReasoningProps) => React.JSX.Element>;
18
+ declare const ReasoningTrigger: React.MemoExoticComponent<({ children, className, getThinkingMessage, ...props }: ReasoningTriggerProps) => React.JSX.Element>;
19
+ declare const ReasoningContent: React.MemoExoticComponent<({ children, className, ...props }: ReasoningContentProps) => React.JSX.Element>;
20
+ export { Reasoning, ReasoningContent, ReasoningTrigger };
21
+ export type { ReasoningContentProps, ReasoningProps, ReasoningTriggerProps };
@@ -0,0 +1,106 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cjk } from "@streamdown/cjk";
3
+ import { code } from "@streamdown/code";
4
+ import { math } from "@streamdown/math";
5
+ import { mermaid } from "@streamdown/mermaid";
6
+ import { BrainIcon, ChevronDownIcon } from "lucide-react";
7
+ import { createContext, memo, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
8
+ import { Streamdown } from "streamdown";
9
+ import { Shimmer } from "@ciridae/ui-agent/shimmer";
10
+ import "@ciridae/ui-agent/message-response.css";
11
+ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@ciridae/ui/collapsible";
12
+ import { cn } from "@ciridae/ui/utils";
13
+ const ReasoningContext = createContext(null);
14
+ const AUTO_CLOSE_DELAY = 1000;
15
+ const MS_IN_SECOND = 1000;
16
+ const streamdownPlugins = { cjk, code, math, mermaid };
17
+ function useReasoningContext() {
18
+ const context = useContext(ReasoningContext);
19
+ if (!context)
20
+ throw new Error("Reasoning components must be used within Reasoning");
21
+ return context;
22
+ }
23
+ const Reasoning = memo(function Reasoning({ children, className, defaultOpen, duration: durationProp, isStreaming = false, onOpenChange, open, ...props }) {
24
+ const { duration, handleOpenChange, isOpen, setIsOpen } = useReasoningState({
25
+ defaultOpen,
26
+ durationProp,
27
+ isStreaming,
28
+ onOpenChange,
29
+ open,
30
+ });
31
+ const contextValue = useMemo(() => ({ duration, isOpen, isStreaming, setIsOpen }), [duration, isOpen, isStreaming, setIsOpen]);
32
+ return (_jsx(ReasoningContext.Provider, { value: contextValue, children: _jsx(Collapsible, { "data-slot": "reasoning", className: cn("rounded-lg border bg-card text-card-foreground", className), onOpenChange: handleOpenChange, open: isOpen, ...props, children: children }) }));
33
+ });
34
+ function useReasoningState({ defaultOpen, durationProp, isStreaming, onOpenChange, open, }) {
35
+ const [internalOpen, setInternalOpen] = useState(defaultOpen ?? isStreaming);
36
+ const [internalDuration, setInternalDuration] = useState(durationProp);
37
+ const hasAutoClosedRef = useRef(false);
38
+ const hasEverStreamedRef = useRef(isStreaming);
39
+ const userClosedDuringStreamingRef = useRef(false);
40
+ const wasStreamingRef = useRef(isStreaming);
41
+ const startTimeRef = useRef(isStreaming ? Date.now() : null);
42
+ const isControlled = open !== undefined;
43
+ const isOpen = open ?? internalOpen;
44
+ const duration = durationProp ?? internalDuration;
45
+ const isExplicitlyClosed = defaultOpen === false;
46
+ const setIsOpen = useCallback((nextOpen) => {
47
+ if (!isControlled)
48
+ setInternalOpen(nextOpen);
49
+ onOpenChange?.(nextOpen);
50
+ }, [isControlled, onOpenChange]);
51
+ const handleOpenChange = useCallback((nextOpen) => {
52
+ if (isStreaming)
53
+ userClosedDuringStreamingRef.current = !nextOpen;
54
+ setIsOpen(nextOpen);
55
+ }, [isStreaming, setIsOpen]);
56
+ useEffect(() => {
57
+ if (durationProp !== undefined)
58
+ setInternalDuration(durationProp);
59
+ }, [durationProp]);
60
+ useEffect(() => {
61
+ const streamStarted = isStreaming && !wasStreamingRef.current;
62
+ wasStreamingRef.current = isStreaming;
63
+ if (isStreaming) {
64
+ hasEverStreamedRef.current = true;
65
+ hasAutoClosedRef.current = false;
66
+ if (streamStarted)
67
+ userClosedDuringStreamingRef.current = false;
68
+ startTimeRef.current ?? (startTimeRef.current = Date.now());
69
+ return;
70
+ }
71
+ if (startTimeRef.current !== null) {
72
+ setInternalDuration(Math.max(1, Math.ceil((Date.now() - startTimeRef.current) / MS_IN_SECOND)));
73
+ startTimeRef.current = null;
74
+ }
75
+ }, [isStreaming]);
76
+ useEffect(() => {
77
+ if (isStreaming && !isOpen && !isExplicitlyClosed && !userClosedDuringStreamingRef.current) {
78
+ setIsOpen(true);
79
+ }
80
+ }, [isExplicitlyClosed, isOpen, isStreaming, setIsOpen]);
81
+ useEffect(() => {
82
+ if (!hasEverStreamedRef.current || isStreaming || !isOpen || hasAutoClosedRef.current)
83
+ return;
84
+ const timer = window.setTimeout(() => {
85
+ hasAutoClosedRef.current = true;
86
+ setIsOpen(false);
87
+ }, AUTO_CLOSE_DELAY);
88
+ return () => window.clearTimeout(timer);
89
+ }, [isOpen, isStreaming, setIsOpen]);
90
+ return { duration, handleOpenChange, isOpen, setIsOpen };
91
+ }
92
+ const ReasoningTrigger = memo(function ReasoningTrigger({ children, className, getThinkingMessage = defaultGetThinkingMessage, ...props }) {
93
+ const { duration, isOpen, isStreaming } = useReasoningContext();
94
+ return (_jsxs(CollapsibleTrigger, { "data-slot": "reasoning-trigger", className: cn("group flex w-full items-center justify-between gap-3 px-3 py-2 text-sm transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:ring-[var(--focus-ring-width)] focus-visible:ring-ring focus-visible:outline-none", className), ...props, children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx(BrainIcon, { "aria-hidden": "true", className: "size-4 shrink-0 text-muted-foreground" }), _jsx("span", { className: "min-w-0 truncate", children: children ?? getThinkingMessage(isStreaming, duration) })] }), _jsx(ChevronDownIcon, { "aria-hidden": "true", className: cn("size-4 shrink-0 text-muted-foreground transition-transform", isOpen ? "rotate-180" : undefined) })] }));
95
+ });
96
+ const ReasoningContent = memo(function ReasoningContent({ children, className, ...props }) {
97
+ return (_jsx(CollapsibleContent, { "data-slot": "reasoning-content", className: cn("border-t px-3 py-3 text-sm", className), ...props, children: _jsx(Streamdown, { className: cn("agentic-message-response text-muted-foreground"), plugins: streamdownPlugins, children: children }) }));
98
+ });
99
+ function defaultGetThinkingMessage(isStreaming, duration) {
100
+ if (isStreaming || duration === 0)
101
+ return _jsx(Shimmer, { as: "span", children: "Thinking..." });
102
+ if (duration === undefined)
103
+ return "Thought for a few seconds";
104
+ return `Thought for ${duration} ${duration === 1 ? "second" : "seconds"}`;
105
+ }
106
+ export { Reasoning, ReasoningContent, ReasoningTrigger };
@@ -0,0 +1,13 @@
1
+ import { BookmarkIcon } from "lucide-react";
2
+ import type * as React from "react";
3
+ import { Button } from "@ciridae/ui/button";
4
+ type RunCheckpointProps = React.ComponentProps<"div">;
5
+ type RunCheckpointIconProps = React.ComponentProps<typeof BookmarkIcon>;
6
+ type RunCheckpointTriggerProps = React.ComponentProps<typeof Button> & {
7
+ tooltip?: string;
8
+ };
9
+ declare function RunCheckpoint({ children, className, ...props }: RunCheckpointProps): React.JSX.Element;
10
+ declare function RunCheckpointIcon({ children, className, ...props }: RunCheckpointIconProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element;
11
+ declare function RunCheckpointTrigger({ children, size, tooltip, type, variant, ...props }: RunCheckpointTriggerProps): React.JSX.Element;
12
+ export { RunCheckpoint, RunCheckpointIcon, RunCheckpointTrigger };
13
+ export type { RunCheckpointIconProps, RunCheckpointProps, RunCheckpointTriggerProps };
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { BookmarkIcon } from "lucide-react";
3
+ import { Button } from "@ciridae/ui/button";
4
+ import { Separator } from "@ciridae/ui/separator";
5
+ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@ciridae/ui/tooltip";
6
+ import { cn } from "@ciridae/ui/utils";
7
+ function RunCheckpoint({ children, className, ...props }) {
8
+ return (_jsxs("div", { "data-slot": "run-checkpoint", className: cn("flex items-center gap-1 overflow-hidden text-muted-foreground", className), ...props, children: [children, _jsx(Separator, { className: "min-w-6 flex-1" })] }));
9
+ }
10
+ function RunCheckpointIcon({ children, className, ...props }) {
11
+ return (children ?? (_jsx(BookmarkIcon, { "aria-hidden": "true", className: cn("size-4 shrink-0", className), ...props })));
12
+ }
13
+ function RunCheckpointTrigger({ children, size = "sm", tooltip, type = "button", variant = "ghost", ...props }) {
14
+ const button = (_jsx(Button, { "data-slot": "run-checkpoint-trigger", size: size, type: type, variant: variant, ...props, children: children }));
15
+ if (!tooltip)
16
+ return button;
17
+ return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: button }), _jsx(TooltipContent, { align: "start", side: "bottom", children: tooltip })] }) }));
18
+ }
19
+ export { RunCheckpoint, RunCheckpointIcon, RunCheckpointTrigger };
@@ -0,0 +1,30 @@
1
+ import type { LucideIcon } from "lucide-react";
2
+ import type * as React from "react";
3
+ import { Badge } from "@ciridae/ui/badge";
4
+ type RunTraceProps = React.ComponentProps<"div"> & {
5
+ defaultOpen?: boolean;
6
+ onOpenChange?: (open: boolean) => void;
7
+ open?: boolean;
8
+ };
9
+ type RunTraceHeaderProps = React.ComponentProps<"button">;
10
+ type RunTraceContentProps = React.ComponentProps<"div">;
11
+ type RunTraceStepProps = React.ComponentProps<"div"> & {
12
+ description?: React.ReactNode;
13
+ icon?: LucideIcon;
14
+ label: React.ReactNode;
15
+ status?: "active" | "complete" | "pending";
16
+ };
17
+ type RunTraceSearchResultsProps = React.ComponentProps<"div">;
18
+ type RunTraceSearchResultProps = React.ComponentProps<typeof Badge>;
19
+ type RunTraceImageProps = React.ComponentProps<"div"> & {
20
+ caption?: string;
21
+ };
22
+ declare const RunTrace: React.MemoExoticComponent<({ children, className, defaultOpen, onOpenChange, open, ...props }: RunTraceProps) => React.JSX.Element>;
23
+ declare const RunTraceHeader: React.MemoExoticComponent<({ children, className, onClick, type, ...props }: RunTraceHeaderProps) => React.JSX.Element>;
24
+ declare const RunTraceContent: React.MemoExoticComponent<({ children, className, ...props }: RunTraceContentProps) => React.JSX.Element | null>;
25
+ declare const RunTraceStep: React.MemoExoticComponent<({ children, className, description, icon: Icon, label, status, ...props }: RunTraceStepProps) => React.JSX.Element>;
26
+ declare function RunTraceSearchResults({ className, ...props }: RunTraceSearchResultsProps): React.JSX.Element;
27
+ declare function RunTraceSearchResult({ className, variant, ...props }: RunTraceSearchResultProps): React.JSX.Element;
28
+ declare function RunTraceImage({ caption, children, className, ...props }: RunTraceImageProps): React.JSX.Element;
29
+ export { RunTrace, RunTraceContent, RunTraceHeader, RunTraceImage, RunTraceSearchResult, RunTraceSearchResults, RunTraceStep, };
30
+ export type { RunTraceContentProps, RunTraceHeaderProps, RunTraceImageProps, RunTraceProps, RunTraceSearchResultProps, RunTraceSearchResultsProps, RunTraceStepProps, };