@yourgpt/copilot-sdk 0.1.1 → 1.0.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/{thread-CLmfwine.d.ts → ThreadManager-BCVt-_k_.d.cts} +376 -223
- package/dist/{thread-CLmfwine.d.cts → ThreadManager-BjC15mh8.d.ts} +376 -223
- package/dist/{chunk-IH7WXWX4.cjs → chunk-42YQ4ATO.cjs} +889 -2
- package/dist/chunk-42YQ4ATO.cjs.map +1 -0
- package/dist/{chunk-R452HH3J.cjs → chunk-BN75ZW24.cjs} +455 -26
- package/dist/chunk-BN75ZW24.cjs.map +1 -0
- package/dist/{chunk-QWQELTEB.js → chunk-QSEGNATZ.js} +882 -3
- package/dist/chunk-QSEGNATZ.js.map +1 -0
- package/dist/{chunk-FO75W5UI.js → chunk-XAVZZVUL.js} +428 -4
- package/dist/chunk-XAVZZVUL.js.map +1 -0
- package/dist/core/index.cjs +99 -71
- package/dist/core/index.d.cts +4 -4
- package/dist/core/index.d.ts +4 -4
- package/dist/core/index.js +1 -1
- package/dist/react/index.cjs +66 -34
- package/dist/react/index.d.cts +371 -5
- package/dist/react/index.d.ts +371 -5
- package/dist/react/index.js +2 -2
- package/dist/{tools-eeJ5iEC4.d.ts → types-BtAaOV07.d.cts} +367 -1
- package/dist/{tools-eeJ5iEC4.d.cts → types-BtAaOV07.d.ts} +367 -1
- package/dist/ui/index.cjs +1703 -467
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +333 -38
- package/dist/ui/index.d.ts +333 -38
- package/dist/ui/index.js +1699 -467
- package/dist/ui/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FO75W5UI.js.map +0 -1
- package/dist/chunk-IH7WXWX4.cjs.map +0 -1
- package/dist/chunk-QWQELTEB.js.map +0 -1
- package/dist/chunk-R452HH3J.cjs.map +0 -1
package/dist/ui/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkBN75ZW24_cjs = require('../chunk-BN75ZW24.cjs');
|
|
4
|
+
var chunk42YQ4ATO_cjs = require('../chunk-42YQ4ATO.cjs');
|
|
5
5
|
var clsx = require('clsx');
|
|
6
6
|
var tailwindMerge = require('tailwind-merge');
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
@@ -17,6 +17,7 @@ var useStickToBottom = require('use-stick-to-bottom');
|
|
|
17
17
|
var tooltip = require('@base-ui/react/tooltip');
|
|
18
18
|
var AvatarPrimitive = require('@radix-ui/react-avatar');
|
|
19
19
|
var HoverCardPrimitive = require('@radix-ui/react-hover-card');
|
|
20
|
+
var popover = require('@base-ui/react/popover');
|
|
20
21
|
|
|
21
22
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
22
23
|
|
|
@@ -893,12 +894,13 @@ var MessageAvatar = ({
|
|
|
893
894
|
src,
|
|
894
895
|
alt,
|
|
895
896
|
fallback,
|
|
897
|
+
fallbackIcon,
|
|
896
898
|
delayMs,
|
|
897
899
|
className
|
|
898
900
|
}) => {
|
|
899
901
|
return /* @__PURE__ */ jsxRuntime.jsxs(Avatar, { className: cn("size-7 shrink-0", className), children: [
|
|
900
902
|
/* @__PURE__ */ jsxRuntime.jsx(AvatarImage, { src, alt }),
|
|
901
|
-
|
|
903
|
+
/* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { delayMs, children: fallbackIcon || fallback })
|
|
902
904
|
] });
|
|
903
905
|
};
|
|
904
906
|
var proseSizeMap = {
|
|
@@ -1932,6 +1934,27 @@ function AlertTriangleIcon({ className }) {
|
|
|
1932
1934
|
}
|
|
1933
1935
|
);
|
|
1934
1936
|
}
|
|
1937
|
+
function ArrowUpRightIcon({ className }) {
|
|
1938
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1939
|
+
"svg",
|
|
1940
|
+
{
|
|
1941
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1942
|
+
width: "24",
|
|
1943
|
+
height: "24",
|
|
1944
|
+
viewBox: "0 0 24 24",
|
|
1945
|
+
fill: "none",
|
|
1946
|
+
stroke: "currentColor",
|
|
1947
|
+
strokeWidth: "2",
|
|
1948
|
+
strokeLinecap: "round",
|
|
1949
|
+
strokeLinejoin: "round",
|
|
1950
|
+
className,
|
|
1951
|
+
children: [
|
|
1952
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 7h10v10" }),
|
|
1953
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 17 17 7" })
|
|
1954
|
+
]
|
|
1955
|
+
}
|
|
1956
|
+
);
|
|
1957
|
+
}
|
|
1935
1958
|
var ConfirmationContext = React8__namespace.createContext(null);
|
|
1936
1959
|
function useConfirmationContext() {
|
|
1937
1960
|
const context = React8__namespace.useContext(ConfirmationContext);
|
|
@@ -3004,173 +3027,722 @@ function SimpleModelSelector({
|
|
|
3004
3027
|
}
|
|
3005
3028
|
);
|
|
3006
3029
|
}
|
|
3007
|
-
function
|
|
3008
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
3009
|
-
|
|
3030
|
+
function Popover({ children, open, defaultOpen, onOpenChange }) {
|
|
3031
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3032
|
+
popover.Popover.Root,
|
|
3033
|
+
{
|
|
3034
|
+
open,
|
|
3035
|
+
defaultOpen,
|
|
3036
|
+
onOpenChange,
|
|
3037
|
+
children
|
|
3038
|
+
}
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
function PopoverTrigger({
|
|
3042
|
+
children,
|
|
3043
|
+
asChild,
|
|
3044
|
+
className,
|
|
3045
|
+
...props
|
|
3046
|
+
}) {
|
|
3047
|
+
if (asChild && React8__namespace.isValidElement(children)) {
|
|
3048
|
+
return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { render: children, className, ...props });
|
|
3049
|
+
}
|
|
3050
|
+
return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Trigger, { className, ...props, children });
|
|
3051
|
+
}
|
|
3052
|
+
function PopoverContent({
|
|
3053
|
+
children,
|
|
3054
|
+
className,
|
|
3055
|
+
side = "bottom",
|
|
3056
|
+
align = "start",
|
|
3057
|
+
sideOffset = 4
|
|
3058
|
+
}) {
|
|
3059
|
+
return /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(popover.Popover.Positioner, { side, align, sideOffset, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3060
|
+
popover.Popover.Popup,
|
|
3010
3061
|
{
|
|
3011
3062
|
className: cn(
|
|
3012
|
-
"
|
|
3063
|
+
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
3064
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
3065
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
3066
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
3067
|
+
"data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2",
|
|
3068
|
+
"data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
3013
3069
|
className
|
|
3014
3070
|
),
|
|
3071
|
+
children
|
|
3072
|
+
}
|
|
3073
|
+
) }) });
|
|
3074
|
+
}
|
|
3075
|
+
function formatDate(date) {
|
|
3076
|
+
const now = /* @__PURE__ */ new Date();
|
|
3077
|
+
const diff = now.getTime() - date.getTime();
|
|
3078
|
+
if (diff < 60 * 1e3) {
|
|
3079
|
+
return "Just now";
|
|
3080
|
+
}
|
|
3081
|
+
if (diff < 60 * 60 * 1e3) {
|
|
3082
|
+
const mins = Math.floor(diff / (60 * 1e3));
|
|
3083
|
+
return `${mins}m ago`;
|
|
3084
|
+
}
|
|
3085
|
+
if (diff < 24 * 60 * 60 * 1e3) {
|
|
3086
|
+
const hours = Math.floor(diff / (60 * 60 * 1e3));
|
|
3087
|
+
return `${hours}h ago`;
|
|
3088
|
+
}
|
|
3089
|
+
if (diff < 7 * 24 * 60 * 60 * 1e3) {
|
|
3090
|
+
const days = Math.floor(diff / (24 * 60 * 60 * 1e3));
|
|
3091
|
+
return `${days}d ago`;
|
|
3092
|
+
}
|
|
3093
|
+
return date.toLocaleDateString();
|
|
3094
|
+
}
|
|
3095
|
+
function ChevronIcon({ className }) {
|
|
3096
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3097
|
+
"svg",
|
|
3098
|
+
{
|
|
3099
|
+
className: cn("w-4 h-4", className),
|
|
3100
|
+
fill: "none",
|
|
3101
|
+
viewBox: "0 0 24 24",
|
|
3102
|
+
stroke: "currentColor",
|
|
3103
|
+
strokeWidth: 2,
|
|
3104
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M19 9l-7 7-7-7" })
|
|
3105
|
+
}
|
|
3106
|
+
);
|
|
3107
|
+
}
|
|
3108
|
+
function PlusIcon2({ className }) {
|
|
3109
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3110
|
+
"svg",
|
|
3111
|
+
{
|
|
3112
|
+
className: cn("w-4 h-4", className),
|
|
3113
|
+
fill: "none",
|
|
3114
|
+
viewBox: "0 0 24 24",
|
|
3115
|
+
stroke: "currentColor",
|
|
3116
|
+
strokeWidth: 2,
|
|
3117
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
|
|
3118
|
+
}
|
|
3119
|
+
);
|
|
3120
|
+
}
|
|
3121
|
+
function CheckIcon2({ className }) {
|
|
3122
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3123
|
+
"svg",
|
|
3124
|
+
{
|
|
3125
|
+
className: cn("w-4 h-4", className),
|
|
3126
|
+
fill: "none",
|
|
3127
|
+
viewBox: "0 0 24 24",
|
|
3128
|
+
stroke: "currentColor",
|
|
3129
|
+
strokeWidth: 2,
|
|
3130
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" })
|
|
3131
|
+
}
|
|
3132
|
+
);
|
|
3133
|
+
}
|
|
3134
|
+
function TrashIcon({ className }) {
|
|
3135
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3136
|
+
"svg",
|
|
3137
|
+
{
|
|
3138
|
+
className: cn("w-4 h-4", className),
|
|
3139
|
+
fill: "none",
|
|
3140
|
+
viewBox: "0 0 24 24",
|
|
3141
|
+
stroke: "currentColor",
|
|
3142
|
+
strokeWidth: 2,
|
|
3015
3143
|
children: [
|
|
3016
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
3017
|
-
|
|
3018
|
-
"
|
|
3144
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3 6h18" }),
|
|
3145
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3146
|
+
"path",
|
|
3019
3147
|
{
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3148
|
+
strokeLinecap: "round",
|
|
3149
|
+
strokeLinejoin: "round",
|
|
3150
|
+
d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"
|
|
3151
|
+
}
|
|
3152
|
+
),
|
|
3153
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3154
|
+
"path",
|
|
3155
|
+
{
|
|
3156
|
+
strokeLinecap: "round",
|
|
3157
|
+
strokeLinejoin: "round",
|
|
3158
|
+
d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"
|
|
3025
3159
|
}
|
|
3026
3160
|
)
|
|
3027
3161
|
]
|
|
3028
3162
|
}
|
|
3029
3163
|
);
|
|
3030
3164
|
}
|
|
3031
|
-
function
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
}
|
|
3048
|
-
function DefaultMessage({
|
|
3049
|
-
message,
|
|
3050
|
-
userAvatar,
|
|
3051
|
-
assistantAvatar,
|
|
3052
|
-
showUserAvatar = false,
|
|
3053
|
-
userMessageClassName,
|
|
3054
|
-
assistantMessageClassName,
|
|
3055
|
-
size = "sm",
|
|
3056
|
-
isLastMessage = false,
|
|
3057
|
-
isLoading = false,
|
|
3058
|
-
registeredTools,
|
|
3059
|
-
toolRenderers,
|
|
3060
|
-
onApproveToolExecution,
|
|
3061
|
-
onRejectToolExecution,
|
|
3062
|
-
showFollowUps = true,
|
|
3063
|
-
onFollowUpClick,
|
|
3064
|
-
followUpClassName,
|
|
3065
|
-
followUpButtonClassName
|
|
3165
|
+
function ThreadPicker({
|
|
3166
|
+
value,
|
|
3167
|
+
threads,
|
|
3168
|
+
onSelect,
|
|
3169
|
+
onDeleteThread,
|
|
3170
|
+
onNewThread,
|
|
3171
|
+
placeholder = "Select conversation...",
|
|
3172
|
+
newThreadLabel = "New conversation",
|
|
3173
|
+
disabled = false,
|
|
3174
|
+
loading = false,
|
|
3175
|
+
size = "md",
|
|
3176
|
+
className,
|
|
3177
|
+
buttonClassName,
|
|
3178
|
+
dropdownClassName,
|
|
3179
|
+
itemClassName,
|
|
3180
|
+
newButtonClassName
|
|
3066
3181
|
}) {
|
|
3067
|
-
const
|
|
3068
|
-
const
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3182
|
+
const [isOpen, setIsOpen] = React8__namespace.useState(false);
|
|
3183
|
+
const selectedThread = React8__namespace.useMemo(() => {
|
|
3184
|
+
if (!value) return null;
|
|
3185
|
+
return threads.find((t) => t.id === value) ?? null;
|
|
3186
|
+
}, [value, threads]);
|
|
3187
|
+
const handleSelect = (threadId) => {
|
|
3188
|
+
onSelect?.(threadId);
|
|
3189
|
+
setIsOpen(false);
|
|
3190
|
+
};
|
|
3191
|
+
const handleNewThread = () => {
|
|
3192
|
+
onNewThread?.();
|
|
3193
|
+
setIsOpen(false);
|
|
3194
|
+
};
|
|
3195
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [
|
|
3196
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3197
|
+
PopoverTrigger,
|
|
3080
3198
|
{
|
|
3199
|
+
disabled: disabled || loading,
|
|
3081
3200
|
className: cn(
|
|
3082
|
-
"flex gap-
|
|
3083
|
-
|
|
3201
|
+
"flex items-center gap-1 w-full",
|
|
3202
|
+
disabled && "opacity-50 cursor-not-allowed",
|
|
3203
|
+
className,
|
|
3204
|
+
buttonClassName
|
|
3084
3205
|
),
|
|
3085
3206
|
children: [
|
|
3086
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
{
|
|
3090
|
-
className: cn(
|
|
3091
|
-
"rounded-lg px-4 py-2 bg-primary text-primary-foreground",
|
|
3092
|
-
userMessageClassName
|
|
3093
|
-
),
|
|
3094
|
-
size,
|
|
3095
|
-
children: message.content
|
|
3096
|
-
}
|
|
3097
|
-
),
|
|
3098
|
-
hasAttachments && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, { attachment }, index)) })
|
|
3099
|
-
] }),
|
|
3100
|
-
showUserAvatar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3101
|
-
MessageAvatar,
|
|
3207
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1 text-xs ", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: "Loading..." }) : selectedThread ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium text-muted-foreground hover:text-foreground", children: selectedThread.title || "Untitled conversation" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: placeholder }) }),
|
|
3208
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3209
|
+
ChevronIcon,
|
|
3102
3210
|
{
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3211
|
+
className: cn(
|
|
3212
|
+
"flex-shrink-0 size-3 text-muted-foreground transition-transform",
|
|
3213
|
+
isOpen && "rotate-180"
|
|
3214
|
+
)
|
|
3106
3215
|
}
|
|
3107
3216
|
)
|
|
3108
3217
|
]
|
|
3109
3218
|
}
|
|
3110
|
-
);
|
|
3111
|
-
}
|
|
3112
|
-
const pendingApprovalTools = message.toolExecutions?.filter(
|
|
3113
|
-
(exec) => exec.approvalStatus === "required"
|
|
3114
|
-
);
|
|
3115
|
-
const completedTools = message.toolExecutions?.filter(
|
|
3116
|
-
(exec) => exec.approvalStatus !== "required"
|
|
3117
|
-
);
|
|
3118
|
-
const hasCustomRender = (toolName) => {
|
|
3119
|
-
if (toolRenderers?.[toolName]) return true;
|
|
3120
|
-
const toolDef = registeredTools?.find((t) => t.name === toolName);
|
|
3121
|
-
if (toolDef?.render) return true;
|
|
3122
|
-
return false;
|
|
3123
|
-
};
|
|
3124
|
-
const toolsWithCustomRender = completedTools?.filter(
|
|
3125
|
-
(exec) => hasCustomRender(exec.name)
|
|
3126
|
-
);
|
|
3127
|
-
const toolsWithoutCustomRender = completedTools?.filter(
|
|
3128
|
-
(exec) => !hasCustomRender(exec.name)
|
|
3129
|
-
);
|
|
3130
|
-
const toolSteps = toolsWithoutCustomRender?.map((exec) => ({
|
|
3131
|
-
id: exec.id,
|
|
3132
|
-
name: exec.name,
|
|
3133
|
-
args: exec.args,
|
|
3134
|
-
status: exec.status,
|
|
3135
|
-
result: exec.result,
|
|
3136
|
-
error: exec.error
|
|
3137
|
-
}));
|
|
3138
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(Message, { className: "flex gap-2", children: [
|
|
3139
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3140
|
-
MessageAvatar,
|
|
3141
|
-
{
|
|
3142
|
-
src: assistantAvatar.src || "",
|
|
3143
|
-
alt: "Assistant",
|
|
3144
|
-
fallback: assistantAvatar.fallback,
|
|
3145
|
-
className: "bg-primary text-primary-foreground"
|
|
3146
|
-
}
|
|
3147
3219
|
),
|
|
3148
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3220
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3221
|
+
PopoverContent,
|
|
3222
|
+
{
|
|
3223
|
+
align: "start",
|
|
3224
|
+
className: cn(
|
|
3225
|
+
"w-[var(--anchor-width)] min-w-[250px] p-0 max-h-[300px] overflow-auto",
|
|
3226
|
+
dropdownClassName
|
|
3227
|
+
),
|
|
3228
|
+
children: [
|
|
3229
|
+
onNewThread && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3230
|
+
"button",
|
|
3231
|
+
{
|
|
3232
|
+
type: "button",
|
|
3233
|
+
onClick: handleNewThread,
|
|
3234
|
+
className: cn(
|
|
3235
|
+
"flex items-center gap-2 w-full px-2.5 py-1.5 text-left",
|
|
3236
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
3237
|
+
"focus:bg-accent focus:text-accent-foreground focus:outline-none",
|
|
3238
|
+
"border-b",
|
|
3239
|
+
newButtonClassName
|
|
3240
|
+
),
|
|
3241
|
+
children: [
|
|
3242
|
+
/* @__PURE__ */ jsxRuntime.jsx(PlusIcon2, { className: "text-primary size-3" }),
|
|
3243
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-xs", children: newThreadLabel })
|
|
3244
|
+
]
|
|
3245
|
+
}
|
|
3163
3246
|
),
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3247
|
+
threads.length > 0 ? threads.map((thread) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3248
|
+
"div",
|
|
3249
|
+
{
|
|
3250
|
+
className: cn(
|
|
3251
|
+
"group flex items-center gap-1 w-full px-2.5 py-1.5",
|
|
3252
|
+
"hover:bg-accent hover:text-accent-foreground",
|
|
3253
|
+
"focus-within:bg-accent focus-within:text-accent-foreground",
|
|
3254
|
+
value === thread.id && "bg-accent",
|
|
3255
|
+
itemClassName
|
|
3256
|
+
),
|
|
3257
|
+
children: [
|
|
3258
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3259
|
+
"button",
|
|
3260
|
+
{
|
|
3261
|
+
type: "button",
|
|
3262
|
+
onClick: () => handleSelect(thread.id),
|
|
3263
|
+
className: "flex-1 flex flex-col gap-0.5 text-left focus:outline-none min-w-0",
|
|
3264
|
+
children: [
|
|
3265
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
3266
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-xs truncate", children: thread.title || "Untitled conversation" }),
|
|
3267
|
+
value === thread.id && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon2, { className: "flex-shrink-0 text-primary size-3" })
|
|
3268
|
+
] }),
|
|
3269
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-[11px] text-muted-foreground", children: [
|
|
3270
|
+
thread.preview && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate max-w-[180px]", children: thread.preview }),
|
|
3271
|
+
thread.preview && thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: "\xB7" }),
|
|
3272
|
+
thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: formatDate(thread.updatedAt) })
|
|
3273
|
+
] })
|
|
3274
|
+
]
|
|
3275
|
+
}
|
|
3276
|
+
),
|
|
3277
|
+
onDeleteThread && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3278
|
+
"button",
|
|
3279
|
+
{
|
|
3280
|
+
type: "button",
|
|
3281
|
+
onClick: (e) => {
|
|
3282
|
+
e.stopPropagation();
|
|
3283
|
+
onDeleteThread(thread.id);
|
|
3284
|
+
},
|
|
3285
|
+
className: "flex-shrink-0 p-1 rounded opacity-0 group-hover:opacity-100 text-muted-foreground hover:text-destructive hover:bg-destructive/10 transition-all focus:opacity-100 focus:outline-none",
|
|
3286
|
+
"aria-label": "Delete thread",
|
|
3287
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, { className: "size-3" })
|
|
3288
|
+
}
|
|
3289
|
+
)
|
|
3290
|
+
]
|
|
3291
|
+
},
|
|
3292
|
+
thread.id
|
|
3293
|
+
)) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2.5 py-3 text-center text-xs text-muted-foreground", children: "No conversations yet" })
|
|
3294
|
+
]
|
|
3295
|
+
}
|
|
3296
|
+
)
|
|
3297
|
+
] });
|
|
3298
|
+
}
|
|
3299
|
+
function formatDate2(date) {
|
|
3300
|
+
const now = /* @__PURE__ */ new Date();
|
|
3301
|
+
const diff = now.getTime() - date.getTime();
|
|
3302
|
+
if (diff < 60 * 1e3) {
|
|
3303
|
+
return "Just now";
|
|
3304
|
+
}
|
|
3305
|
+
if (diff < 60 * 60 * 1e3) {
|
|
3306
|
+
const mins = Math.floor(diff / (60 * 1e3));
|
|
3307
|
+
return `${mins}m ago`;
|
|
3308
|
+
}
|
|
3309
|
+
if (diff < 24 * 60 * 60 * 1e3) {
|
|
3310
|
+
const hours = Math.floor(diff / (60 * 60 * 1e3));
|
|
3311
|
+
return `${hours}h ago`;
|
|
3312
|
+
}
|
|
3313
|
+
if (diff < 7 * 24 * 60 * 60 * 1e3) {
|
|
3314
|
+
const days = Math.floor(diff / (24 * 60 * 60 * 1e3));
|
|
3315
|
+
return `${days}d ago`;
|
|
3316
|
+
}
|
|
3317
|
+
return date.toLocaleDateString();
|
|
3318
|
+
}
|
|
3319
|
+
function TrashIcon2({ className }) {
|
|
3320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3321
|
+
"svg",
|
|
3322
|
+
{
|
|
3323
|
+
className: cn("w-4 h-4", className),
|
|
3324
|
+
fill: "none",
|
|
3325
|
+
viewBox: "0 0 24 24",
|
|
3326
|
+
stroke: "currentColor",
|
|
3327
|
+
strokeWidth: 2,
|
|
3328
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3329
|
+
"path",
|
|
3330
|
+
{
|
|
3331
|
+
strokeLinecap: "round",
|
|
3332
|
+
strokeLinejoin: "round",
|
|
3333
|
+
d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
3334
|
+
}
|
|
3335
|
+
)
|
|
3336
|
+
}
|
|
3337
|
+
);
|
|
3338
|
+
}
|
|
3339
|
+
function PlusIcon3({ className }) {
|
|
3340
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3341
|
+
"svg",
|
|
3342
|
+
{
|
|
3343
|
+
className: cn("w-4 h-4", className),
|
|
3344
|
+
fill: "none",
|
|
3345
|
+
viewBox: "0 0 24 24",
|
|
3346
|
+
stroke: "currentColor",
|
|
3347
|
+
strokeWidth: 2,
|
|
3348
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 4v16m8-8H4" })
|
|
3349
|
+
}
|
|
3350
|
+
);
|
|
3351
|
+
}
|
|
3352
|
+
function MessageIcon({ className }) {
|
|
3353
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3354
|
+
"svg",
|
|
3355
|
+
{
|
|
3356
|
+
className: cn("w-4 h-4", className),
|
|
3357
|
+
fill: "none",
|
|
3358
|
+
viewBox: "0 0 24 24",
|
|
3359
|
+
stroke: "currentColor",
|
|
3360
|
+
strokeWidth: 2,
|
|
3361
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3362
|
+
"path",
|
|
3363
|
+
{
|
|
3364
|
+
strokeLinecap: "round",
|
|
3365
|
+
strokeLinejoin: "round",
|
|
3366
|
+
d: "M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z"
|
|
3367
|
+
}
|
|
3368
|
+
)
|
|
3369
|
+
}
|
|
3370
|
+
);
|
|
3371
|
+
}
|
|
3372
|
+
function ThreadCardSkeleton() {
|
|
3373
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 rounded-lg border bg-card animate-pulse", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
3374
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-full bg-muted" }),
|
|
3375
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-2", children: [
|
|
3376
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 w-3/4 bg-muted rounded" }),
|
|
3377
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 w-1/2 bg-muted rounded" })
|
|
3378
|
+
] })
|
|
3379
|
+
] }) });
|
|
3380
|
+
}
|
|
3381
|
+
function ThreadCard({
|
|
3382
|
+
thread,
|
|
3383
|
+
selected = false,
|
|
3384
|
+
onClick,
|
|
3385
|
+
onDelete,
|
|
3386
|
+
showDelete = true,
|
|
3387
|
+
className
|
|
3388
|
+
}) {
|
|
3389
|
+
const [isHovered, setIsHovered] = React8__namespace.useState(false);
|
|
3390
|
+
const handleDelete = (e) => {
|
|
3391
|
+
e.stopPropagation();
|
|
3392
|
+
onDelete?.();
|
|
3393
|
+
};
|
|
3394
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3395
|
+
"button",
|
|
3396
|
+
{
|
|
3397
|
+
type: "button",
|
|
3398
|
+
onClick,
|
|
3399
|
+
onMouseEnter: () => setIsHovered(true),
|
|
3400
|
+
onMouseLeave: () => setIsHovered(false),
|
|
3401
|
+
className: cn(
|
|
3402
|
+
"w-full p-3 rounded-lg border bg-card text-left transition-colors",
|
|
3403
|
+
"hover:bg-accent hover:border-accent-foreground/20",
|
|
3404
|
+
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
3405
|
+
selected && "bg-accent border-primary/50",
|
|
3406
|
+
className
|
|
3407
|
+
),
|
|
3408
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3", children: [
|
|
3409
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3410
|
+
"div",
|
|
3411
|
+
{
|
|
3412
|
+
className: cn(
|
|
3413
|
+
"flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center",
|
|
3414
|
+
selected ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"
|
|
3415
|
+
),
|
|
3416
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(MessageIcon, {})
|
|
3417
|
+
}
|
|
3418
|
+
),
|
|
3419
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
3420
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
3421
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-medium text-sm truncate", children: thread.title || "Untitled conversation" }),
|
|
3422
|
+
showDelete && isHovered && onDelete && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3423
|
+
"button",
|
|
3424
|
+
{
|
|
3425
|
+
type: "button",
|
|
3426
|
+
onClick: handleDelete,
|
|
3427
|
+
className: cn(
|
|
3428
|
+
"flex-shrink-0 p-1 rounded",
|
|
3429
|
+
"hover:bg-destructive/10 hover:text-destructive",
|
|
3430
|
+
"focus:outline-none focus:ring-2 focus:ring-destructive"
|
|
3431
|
+
),
|
|
3432
|
+
"aria-label": "Delete conversation",
|
|
3433
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon2, { className: "w-3.5 h-3.5" })
|
|
3434
|
+
}
|
|
3435
|
+
)
|
|
3436
|
+
] }),
|
|
3437
|
+
thread.preview && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground truncate mt-0.5", children: thread.preview }),
|
|
3438
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mt-1 text-xs text-muted-foreground", children: [
|
|
3439
|
+
thread.messageCount !== void 0 && thread.messageCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
3440
|
+
thread.messageCount,
|
|
3441
|
+
" messages"
|
|
3442
|
+
] }),
|
|
3443
|
+
thread.messageCount !== void 0 && thread.messageCount > 0 && thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\xB7" }),
|
|
3444
|
+
thread.updatedAt && /* @__PURE__ */ jsxRuntime.jsx("span", { children: formatDate2(thread.updatedAt) })
|
|
3445
|
+
] })
|
|
3446
|
+
] })
|
|
3447
|
+
] })
|
|
3448
|
+
}
|
|
3449
|
+
);
|
|
3450
|
+
}
|
|
3451
|
+
function ThreadList({
|
|
3452
|
+
threads,
|
|
3453
|
+
selectedId,
|
|
3454
|
+
onSelect,
|
|
3455
|
+
onDelete,
|
|
3456
|
+
onNewThread,
|
|
3457
|
+
newThreadLabel = "New conversation",
|
|
3458
|
+
loading = false,
|
|
3459
|
+
emptyText = "No conversations yet",
|
|
3460
|
+
showDelete = true,
|
|
3461
|
+
className
|
|
3462
|
+
}) {
|
|
3463
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
|
|
3464
|
+
onNewThread && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3465
|
+
"button",
|
|
3466
|
+
{
|
|
3467
|
+
type: "button",
|
|
3468
|
+
onClick: onNewThread,
|
|
3469
|
+
className: cn(
|
|
3470
|
+
"flex items-center gap-2 p-3 rounded-lg border border-dashed",
|
|
3471
|
+
"hover:bg-accent hover:border-accent-foreground/20",
|
|
3472
|
+
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
3473
|
+
"transition-colors"
|
|
3474
|
+
),
|
|
3475
|
+
children: [
|
|
3476
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(PlusIcon3, { className: "text-primary" }) }),
|
|
3477
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-sm", children: newThreadLabel })
|
|
3478
|
+
]
|
|
3479
|
+
}
|
|
3480
|
+
),
|
|
3481
|
+
loading && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3482
|
+
/* @__PURE__ */ jsxRuntime.jsx(ThreadCardSkeleton, {}),
|
|
3483
|
+
/* @__PURE__ */ jsxRuntime.jsx(ThreadCardSkeleton, {}),
|
|
3484
|
+
/* @__PURE__ */ jsxRuntime.jsx(ThreadCardSkeleton, {})
|
|
3485
|
+
] }),
|
|
3486
|
+
!loading && threads.length > 0 && threads.map((thread) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3487
|
+
ThreadCard,
|
|
3488
|
+
{
|
|
3489
|
+
thread,
|
|
3490
|
+
selected: selectedId === thread.id,
|
|
3491
|
+
onClick: () => onSelect?.(thread.id),
|
|
3492
|
+
onDelete: () => onDelete?.(thread.id),
|
|
3493
|
+
showDelete
|
|
3494
|
+
},
|
|
3495
|
+
thread.id
|
|
3496
|
+
)),
|
|
3497
|
+
!loading && threads.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-sm text-muted-foreground", children: emptyText })
|
|
3498
|
+
] });
|
|
3499
|
+
}
|
|
3500
|
+
var CopilotSDKLogo = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3501
|
+
"svg",
|
|
3502
|
+
{
|
|
3503
|
+
width: props.width || 170,
|
|
3504
|
+
height: props.height || 170,
|
|
3505
|
+
viewBox: "0 0 170 170",
|
|
3506
|
+
fill: "none",
|
|
3507
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3508
|
+
...props,
|
|
3509
|
+
className: cn("w-auto h-[30px]", props.className),
|
|
3510
|
+
children: [
|
|
3511
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3512
|
+
"path",
|
|
3513
|
+
{
|
|
3514
|
+
opacity: 0.4,
|
|
3515
|
+
d: "M108.379 0C111.143 0 113.538 1.91574 114.146 4.61243L118.392 23.4631C121.492 37.2253 132.239 47.9726 146.001 51.0727L164.852 55.319C167.549 55.9265 169.465 58.3218 169.465 61.0861C169.465 63.8504 167.549 66.2457 164.852 66.8532L146.001 71.0995C132.239 74.1995 121.492 84.9467 118.392 98.7088L114.146 117.56C113.538 120.257 111.143 122.172 108.379 122.172C105.614 122.172 103.219 120.257 102.611 117.56L98.3651 98.7088C95.2651 84.9467 84.5179 74.1995 70.7558 71.0995L51.9049 66.8532C49.2082 66.2457 47.2924 63.8504 47.2924 61.0861C47.2924 58.3218 49.2082 55.9265 51.9049 55.319L70.7558 51.0727C84.5179 47.9726 95.2651 37.2253 98.3651 23.4631L102.611 4.61243C103.219 1.91574 105.614 0 108.379 0Z",
|
|
3516
|
+
fill: "#6352FF"
|
|
3517
|
+
}
|
|
3518
|
+
),
|
|
3519
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3520
|
+
"path",
|
|
3521
|
+
{
|
|
3522
|
+
d: "M45.3219 78.8207C48.0863 78.8207 50.4816 80.736 51.089 83.4333L54.1221 96.8982C56.1931 106.092 63.3728 113.272 72.5663 115.342L86.0313 118.375C88.7285 118.983 90.6439 121.378 90.6439 124.143C90.6439 126.907 88.7285 129.302 86.0313 129.91L72.5663 132.943C63.3728 135.014 56.1931 142.193 54.1221 151.387L51.089 164.852C50.4816 167.549 48.0863 169.465 45.3219 169.465C42.5576 169.465 40.1623 167.549 39.5549 164.852L36.5218 151.387C34.4507 142.193 27.271 135.014 18.0772 132.943L4.61243 129.91C1.91574 129.302 0 126.907 0 124.143C0 121.378 1.91574 118.983 4.61243 118.375L18.0772 115.342C27.271 113.272 34.4507 106.092 36.5218 96.8982L39.5549 83.4333C40.1623 80.736 42.5576 78.8207 45.3219 78.8207Z",
|
|
3523
|
+
fill: "#523FFF"
|
|
3524
|
+
}
|
|
3525
|
+
),
|
|
3526
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3527
|
+
"line",
|
|
3528
|
+
{
|
|
3529
|
+
x1: 137.266,
|
|
3530
|
+
y1: 162.316,
|
|
3531
|
+
x2: 83.1281,
|
|
3532
|
+
y2: 162.316,
|
|
3533
|
+
stroke: "currentColor",
|
|
3534
|
+
strokeWidth: 11.8231
|
|
3535
|
+
}
|
|
3536
|
+
),
|
|
3537
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3538
|
+
"line",
|
|
3539
|
+
{
|
|
3540
|
+
x1: 160.188,
|
|
3541
|
+
y1: 162.316,
|
|
3542
|
+
x2: 140.811,
|
|
3543
|
+
y2: 162.316,
|
|
3544
|
+
stroke: "currentColor",
|
|
3545
|
+
strokeOpacity: 0.26,
|
|
3546
|
+
strokeWidth: 11.8231
|
|
3547
|
+
}
|
|
3548
|
+
)
|
|
3549
|
+
]
|
|
3550
|
+
}
|
|
3551
|
+
);
|
|
3552
|
+
var copilot_sdk_logo_default = CopilotSDKLogo;
|
|
3553
|
+
var DEFAULT_NAME = "AI Copilot";
|
|
3554
|
+
function ChatHeader({
|
|
3555
|
+
logo,
|
|
3556
|
+
name,
|
|
3557
|
+
title,
|
|
3558
|
+
threadPicker,
|
|
3559
|
+
onClose,
|
|
3560
|
+
className
|
|
3561
|
+
}) {
|
|
3562
|
+
const displayName = name || title || DEFAULT_NAME;
|
|
3563
|
+
const showDefaultLogo = logo === void 0;
|
|
3564
|
+
const showCustomLogo = typeof logo === "string" && logo.length > 0;
|
|
3565
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3566
|
+
"div",
|
|
3567
|
+
{
|
|
3568
|
+
className: cn(
|
|
3569
|
+
"flex flex-col border-b border-border bg-background",
|
|
3570
|
+
className
|
|
3571
|
+
),
|
|
3572
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-4 py-2", children: [
|
|
3573
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 shrink-0", children: [
|
|
3574
|
+
showDefaultLogo && /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "h-6 w-auto" }),
|
|
3575
|
+
showCustomLogo && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3576
|
+
"img",
|
|
3577
|
+
{
|
|
3578
|
+
src: logo,
|
|
3579
|
+
alt: displayName,
|
|
3580
|
+
className: "size-6 rounded-md object-contain"
|
|
3581
|
+
}
|
|
3582
|
+
),
|
|
3583
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3584
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-foreground text-sm mb-0.5", children: displayName }),
|
|
3585
|
+
threadPicker && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: threadPicker })
|
|
3586
|
+
] })
|
|
3587
|
+
] }),
|
|
3588
|
+
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3589
|
+
"button",
|
|
3590
|
+
{
|
|
3591
|
+
type: "button",
|
|
3592
|
+
onClick: onClose,
|
|
3593
|
+
className: "rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
|
|
3594
|
+
"aria-label": "Close chat",
|
|
3595
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, { className: "h-5 w-5" })
|
|
3596
|
+
}
|
|
3597
|
+
)
|
|
3598
|
+
] })
|
|
3599
|
+
}
|
|
3600
|
+
);
|
|
3601
|
+
}
|
|
3602
|
+
function Suggestions({
|
|
3603
|
+
suggestions,
|
|
3604
|
+
onSuggestionClick,
|
|
3605
|
+
className
|
|
3606
|
+
}) {
|
|
3607
|
+
if (!suggestions.length) return null;
|
|
3608
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-wrap gap-2 px-4 py-2", className), children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3609
|
+
"button",
|
|
3610
|
+
{
|
|
3611
|
+
type: "button",
|
|
3612
|
+
onClick: () => onSuggestionClick?.(suggestion),
|
|
3613
|
+
className: "inline-flex items-center rounded-full border bg-background px-3 py-1.5 text-sm transition-colors hover:bg-muted",
|
|
3614
|
+
children: suggestion
|
|
3615
|
+
},
|
|
3616
|
+
index
|
|
3617
|
+
)) });
|
|
3618
|
+
}
|
|
3619
|
+
function DefaultMessage({
|
|
3620
|
+
message,
|
|
3621
|
+
userAvatar,
|
|
3622
|
+
assistantAvatar,
|
|
3623
|
+
showUserAvatar = false,
|
|
3624
|
+
userMessageClassName,
|
|
3625
|
+
assistantMessageClassName,
|
|
3626
|
+
size = "sm",
|
|
3627
|
+
isLastMessage = false,
|
|
3628
|
+
isLoading = false,
|
|
3629
|
+
registeredTools,
|
|
3630
|
+
toolRenderers,
|
|
3631
|
+
onApproveToolExecution,
|
|
3632
|
+
onRejectToolExecution,
|
|
3633
|
+
showFollowUps = true,
|
|
3634
|
+
onFollowUpClick,
|
|
3635
|
+
followUpClassName,
|
|
3636
|
+
followUpButtonClassName
|
|
3637
|
+
}) {
|
|
3638
|
+
const isUser = message.role === "user";
|
|
3639
|
+
const isStreaming = isLastMessage && isLoading;
|
|
3640
|
+
const { cleanContent, followUps } = React8__namespace.useMemo(() => {
|
|
3641
|
+
if (isUser || !message.content) {
|
|
3642
|
+
return { cleanContent: message.content, followUps: [] };
|
|
3643
|
+
}
|
|
3644
|
+
return parseFollowUps(message.content);
|
|
3645
|
+
}, [message.content, isUser]);
|
|
3646
|
+
const shouldShowFollowUps = showFollowUps && !isUser && isLastMessage && !isLoading && followUps.length > 0 && onFollowUpClick;
|
|
3647
|
+
if (isUser) {
|
|
3648
|
+
const hasAttachments = message.attachments && message.attachments.length > 0;
|
|
3649
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3650
|
+
Message,
|
|
3651
|
+
{
|
|
3652
|
+
className: cn(
|
|
3653
|
+
"flex gap-2",
|
|
3654
|
+
showUserAvatar ? "justify-end" : "justify-end"
|
|
3655
|
+
),
|
|
3656
|
+
children: [
|
|
3657
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-end max-w-[80%]", children: [
|
|
3658
|
+
message.content && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3659
|
+
MessageContent,
|
|
3660
|
+
{
|
|
3661
|
+
className: cn(
|
|
3662
|
+
"rounded-lg px-4 py-2 bg-primary text-primary-foreground",
|
|
3663
|
+
userMessageClassName
|
|
3664
|
+
),
|
|
3665
|
+
size,
|
|
3666
|
+
children: message.content
|
|
3667
|
+
}
|
|
3668
|
+
),
|
|
3669
|
+
hasAttachments && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex flex-wrap gap-2 justify-end", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, { attachment }, index)) })
|
|
3670
|
+
] }),
|
|
3671
|
+
showUserAvatar && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3672
|
+
MessageAvatar,
|
|
3673
|
+
{
|
|
3674
|
+
src: userAvatar.src || "",
|
|
3675
|
+
alt: "User",
|
|
3676
|
+
fallback: userAvatar.fallback
|
|
3677
|
+
}
|
|
3678
|
+
)
|
|
3679
|
+
]
|
|
3680
|
+
}
|
|
3681
|
+
);
|
|
3682
|
+
}
|
|
3683
|
+
const pendingApprovalTools = message.toolExecutions?.filter(
|
|
3684
|
+
(exec) => exec.approvalStatus === "required"
|
|
3685
|
+
);
|
|
3686
|
+
const completedTools = message.toolExecutions?.filter(
|
|
3687
|
+
(exec) => exec.approvalStatus !== "required"
|
|
3688
|
+
);
|
|
3689
|
+
const hasCustomRender = (toolName) => {
|
|
3690
|
+
if (toolRenderers?.[toolName]) return true;
|
|
3691
|
+
const toolDef = registeredTools?.find((t) => t.name === toolName);
|
|
3692
|
+
if (toolDef?.render) return true;
|
|
3693
|
+
return false;
|
|
3694
|
+
};
|
|
3695
|
+
const toolsWithCustomRender = completedTools?.filter(
|
|
3696
|
+
(exec) => hasCustomRender(exec.name)
|
|
3697
|
+
);
|
|
3698
|
+
const toolsWithoutCustomRender = completedTools?.filter(
|
|
3699
|
+
(exec) => !hasCustomRender(exec.name)
|
|
3700
|
+
);
|
|
3701
|
+
const toolSteps = toolsWithoutCustomRender?.map((exec) => ({
|
|
3702
|
+
id: exec.id,
|
|
3703
|
+
name: exec.name,
|
|
3704
|
+
args: exec.args,
|
|
3705
|
+
status: exec.status,
|
|
3706
|
+
result: exec.result,
|
|
3707
|
+
error: exec.error
|
|
3708
|
+
}));
|
|
3709
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Message, { className: "flex gap-2", children: [
|
|
3710
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3711
|
+
MessageAvatar,
|
|
3712
|
+
{
|
|
3713
|
+
src: assistantAvatar.src || "",
|
|
3714
|
+
alt: "Assistant",
|
|
3715
|
+
fallback: assistantAvatar.fallback,
|
|
3716
|
+
fallbackIcon: !assistantAvatar.src ? /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
|
|
3717
|
+
className: "bg-background"
|
|
3718
|
+
}
|
|
3719
|
+
),
|
|
3720
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 max-w-[80%]", children: [
|
|
3721
|
+
message.thinking && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3722
|
+
SimpleReasoning,
|
|
3723
|
+
{
|
|
3724
|
+
content: message.thinking,
|
|
3725
|
+
isStreaming,
|
|
3726
|
+
className: "mb-2"
|
|
3727
|
+
}
|
|
3728
|
+
),
|
|
3729
|
+
cleanContent?.trim() && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3730
|
+
MessageContent,
|
|
3731
|
+
{
|
|
3732
|
+
className: cn(
|
|
3733
|
+
"rounded-lg px-4 py-2 bg-muted",
|
|
3734
|
+
assistantMessageClassName
|
|
3735
|
+
),
|
|
3736
|
+
markdown: true,
|
|
3737
|
+
size,
|
|
3738
|
+
children: cleanContent
|
|
3739
|
+
}
|
|
3740
|
+
),
|
|
3741
|
+
toolsWithCustomRender && toolsWithCustomRender.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 space-y-2", children: toolsWithCustomRender.map((exec) => {
|
|
3742
|
+
const Renderer = toolRenderers?.[exec.name];
|
|
3743
|
+
if (Renderer) {
|
|
3744
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3745
|
+
Renderer,
|
|
3174
3746
|
{
|
|
3175
3747
|
execution: {
|
|
3176
3748
|
id: exec.id,
|
|
@@ -3241,125 +3813,465 @@ function DefaultMessage({
|
|
|
3241
3813
|
const output = toolDef.render(renderProps);
|
|
3242
3814
|
return /* @__PURE__ */ jsxRuntime.jsx(React8__namespace.Fragment, { children: output }, tool.id);
|
|
3243
3815
|
}
|
|
3244
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3245
|
-
PermissionConfirmation,
|
|
3816
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3817
|
+
PermissionConfirmation,
|
|
3818
|
+
{
|
|
3819
|
+
state: "pending",
|
|
3820
|
+
toolName: tool.name,
|
|
3821
|
+
message: tool.approvalMessage || `This tool wants to execute. Do you approve?`,
|
|
3822
|
+
onApprove: (permissionLevel) => onApproveToolExecution?.(
|
|
3823
|
+
tool.id,
|
|
3824
|
+
void 0,
|
|
3825
|
+
permissionLevel
|
|
3826
|
+
),
|
|
3827
|
+
onReject: (permissionLevel) => onRejectToolExecution?.(tool.id, void 0, permissionLevel)
|
|
3828
|
+
},
|
|
3829
|
+
tool.id
|
|
3830
|
+
);
|
|
3831
|
+
}) }),
|
|
3832
|
+
message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 flex flex-wrap gap-2", children: message.attachments.map((attachment, index) => /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreview, { attachment }, index)) }),
|
|
3833
|
+
shouldShowFollowUps && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3834
|
+
FollowUpQuestions,
|
|
3835
|
+
{
|
|
3836
|
+
questions: followUps,
|
|
3837
|
+
onSelect: onFollowUpClick,
|
|
3838
|
+
className: followUpClassName,
|
|
3839
|
+
buttonClassName: followUpButtonClassName
|
|
3840
|
+
}
|
|
3841
|
+
)
|
|
3842
|
+
] })
|
|
3843
|
+
] });
|
|
3844
|
+
}
|
|
3845
|
+
function AttachmentPreview({ attachment }) {
|
|
3846
|
+
const [expanded, setExpanded] = React8__namespace.useState(false);
|
|
3847
|
+
if (attachment.type !== "image") {
|
|
3848
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
|
|
3849
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: attachment.type }),
|
|
3850
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: attachment.filename || "Attachment" })
|
|
3851
|
+
] });
|
|
3852
|
+
}
|
|
3853
|
+
let src;
|
|
3854
|
+
if (attachment.url) {
|
|
3855
|
+
src = attachment.url;
|
|
3856
|
+
} else if (attachment.data) {
|
|
3857
|
+
src = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType};base64,${attachment.data}`;
|
|
3858
|
+
} else {
|
|
3859
|
+
return null;
|
|
3860
|
+
}
|
|
3861
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3862
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3863
|
+
"button",
|
|
3864
|
+
{
|
|
3865
|
+
type: "button",
|
|
3866
|
+
onClick: () => setExpanded(true),
|
|
3867
|
+
className: "relative rounded-lg overflow-hidden border bg-muted/50 hover:opacity-90 transition-opacity",
|
|
3868
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3869
|
+
"img",
|
|
3870
|
+
{
|
|
3871
|
+
src,
|
|
3872
|
+
alt: attachment.filename || "Image",
|
|
3873
|
+
className: "max-w-[200px] max-h-[150px] object-cover"
|
|
3874
|
+
}
|
|
3875
|
+
)
|
|
3876
|
+
}
|
|
3877
|
+
),
|
|
3878
|
+
expanded && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3879
|
+
"div",
|
|
3880
|
+
{
|
|
3881
|
+
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80",
|
|
3882
|
+
onClick: () => setExpanded(false),
|
|
3883
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-[90vw] max-h-[90vh]", children: [
|
|
3884
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3885
|
+
"img",
|
|
3886
|
+
{
|
|
3887
|
+
src,
|
|
3888
|
+
alt: attachment.filename || "Image (expanded)",
|
|
3889
|
+
className: "max-w-full max-h-full object-contain rounded-lg"
|
|
3890
|
+
}
|
|
3891
|
+
),
|
|
3892
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3893
|
+
"button",
|
|
3894
|
+
{
|
|
3895
|
+
type: "button",
|
|
3896
|
+
className: "absolute top-2 right-2 bg-white/90 rounded-full p-2 hover:bg-white transition-colors",
|
|
3897
|
+
onClick: (e) => {
|
|
3898
|
+
e.stopPropagation();
|
|
3899
|
+
setExpanded(false);
|
|
3900
|
+
},
|
|
3901
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3902
|
+
"svg",
|
|
3903
|
+
{
|
|
3904
|
+
className: "w-4 h-4",
|
|
3905
|
+
fill: "none",
|
|
3906
|
+
viewBox: "0 0 24 24",
|
|
3907
|
+
stroke: "currentColor",
|
|
3908
|
+
strokeWidth: 2,
|
|
3909
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3910
|
+
"path",
|
|
3911
|
+
{
|
|
3912
|
+
strokeLinecap: "round",
|
|
3913
|
+
strokeLinejoin: "round",
|
|
3914
|
+
d: "M6 18L18 6M6 6l12 12"
|
|
3915
|
+
}
|
|
3916
|
+
)
|
|
3917
|
+
}
|
|
3918
|
+
)
|
|
3919
|
+
}
|
|
3920
|
+
)
|
|
3921
|
+
] })
|
|
3922
|
+
}
|
|
3923
|
+
)
|
|
3924
|
+
] });
|
|
3925
|
+
}
|
|
3926
|
+
var DEFAULT_MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
3927
|
+
var DEFAULT_ALLOWED_TYPES = ["image/*", "application/pdf"];
|
|
3928
|
+
var DEFAULT_TITLE = "How can I help you today?";
|
|
3929
|
+
var DEFAULT_SUBTITLE = "Ask anything and get it done.";
|
|
3930
|
+
var DEFAULT_SUGGESTIONS_LABEL = "Try AI Copilot";
|
|
3931
|
+
var DEFAULT_RECENT_CHATS_LABEL = "Recent chats";
|
|
3932
|
+
var DEFAULT_MAX_RECENT_CHATS = 3;
|
|
3933
|
+
var DEFAULT_VIEW_MORE_LABEL = "View more..";
|
|
3934
|
+
function getAttachmentType(mimeType) {
|
|
3935
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
3936
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
3937
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
3938
|
+
return "file";
|
|
3939
|
+
}
|
|
3940
|
+
function fileToBase64(file) {
|
|
3941
|
+
return new Promise((resolve, reject) => {
|
|
3942
|
+
const reader = new FileReader();
|
|
3943
|
+
reader.onload = () => {
|
|
3944
|
+
if (typeof reader.result === "string") {
|
|
3945
|
+
resolve(reader.result);
|
|
3946
|
+
} else {
|
|
3947
|
+
reject(new Error("Failed to read file"));
|
|
3948
|
+
}
|
|
3949
|
+
};
|
|
3950
|
+
reader.onerror = () => reject(new Error("Failed to read file"));
|
|
3951
|
+
reader.readAsDataURL(file);
|
|
3952
|
+
});
|
|
3953
|
+
}
|
|
3954
|
+
function generateAttachmentId() {
|
|
3955
|
+
return `att_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
3956
|
+
}
|
|
3957
|
+
function ChatWelcome({
|
|
3958
|
+
config,
|
|
3959
|
+
suggestions = [],
|
|
3960
|
+
recentThreads = [],
|
|
3961
|
+
onSendMessage,
|
|
3962
|
+
onSelectThread,
|
|
3963
|
+
onDeleteThread,
|
|
3964
|
+
onViewMoreThreads,
|
|
3965
|
+
isLoading = false,
|
|
3966
|
+
onStop,
|
|
3967
|
+
placeholder = "Type a message...",
|
|
3968
|
+
attachmentsEnabled = true,
|
|
3969
|
+
attachmentsDisabledTooltip = "Attachments not supported by this model",
|
|
3970
|
+
maxFileSize = DEFAULT_MAX_FILE_SIZE,
|
|
3971
|
+
allowedFileTypes = DEFAULT_ALLOWED_TYPES,
|
|
3972
|
+
processAttachment: processAttachmentProp,
|
|
3973
|
+
classNames = {}
|
|
3974
|
+
}) {
|
|
3975
|
+
const [input, setInput] = React8.useState("");
|
|
3976
|
+
const [pendingAttachments, setPendingAttachments] = React8.useState([]);
|
|
3977
|
+
const fileInputRef = React8.useRef(null);
|
|
3978
|
+
const fileInputId = React8.useId();
|
|
3979
|
+
const title = config?.title ?? DEFAULT_TITLE;
|
|
3980
|
+
const subtitle = config?.subtitle ?? DEFAULT_SUBTITLE;
|
|
3981
|
+
const logo = config?.logo;
|
|
3982
|
+
const suggestionsLabel = config?.suggestionsLabel ?? DEFAULT_SUGGESTIONS_LABEL;
|
|
3983
|
+
const showRecentChats = config?.showRecentChats ?? true;
|
|
3984
|
+
config?.recentChatsLabel ?? DEFAULT_RECENT_CHATS_LABEL;
|
|
3985
|
+
const maxRecentChats = config?.maxRecentChats ?? DEFAULT_MAX_RECENT_CHATS;
|
|
3986
|
+
config?.viewMoreLabel ?? DEFAULT_VIEW_MORE_LABEL;
|
|
3987
|
+
const isFileTypeAllowed = React8.useCallback(
|
|
3988
|
+
(file) => {
|
|
3989
|
+
for (const type of allowedFileTypes) {
|
|
3990
|
+
if (type.endsWith("/*")) {
|
|
3991
|
+
const category = type.slice(0, -2);
|
|
3992
|
+
if (file.type.startsWith(category + "/")) return true;
|
|
3993
|
+
} else if (file.type === type) {
|
|
3994
|
+
return true;
|
|
3995
|
+
}
|
|
3996
|
+
}
|
|
3997
|
+
return false;
|
|
3998
|
+
},
|
|
3999
|
+
[allowedFileTypes]
|
|
4000
|
+
);
|
|
4001
|
+
const handleFileSelect = React8.useCallback(
|
|
4002
|
+
async (files) => {
|
|
4003
|
+
if (!files || !attachmentsEnabled) return;
|
|
4004
|
+
for (const file of Array.from(files)) {
|
|
4005
|
+
if (file.size > maxFileSize) {
|
|
4006
|
+
const sizeMB = (maxFileSize / (1024 * 1024)).toFixed(0);
|
|
4007
|
+
console.warn(`File ${file.name} exceeds ${sizeMB}MB limit`);
|
|
4008
|
+
continue;
|
|
4009
|
+
}
|
|
4010
|
+
if (!isFileTypeAllowed(file)) {
|
|
4011
|
+
console.warn(`File type ${file.type} is not allowed`);
|
|
4012
|
+
continue;
|
|
4013
|
+
}
|
|
4014
|
+
const id = generateAttachmentId();
|
|
4015
|
+
const previewUrl = URL.createObjectURL(file);
|
|
4016
|
+
setPendingAttachments((prev) => [
|
|
4017
|
+
...prev,
|
|
4018
|
+
{
|
|
4019
|
+
id,
|
|
4020
|
+
file,
|
|
4021
|
+
previewUrl,
|
|
4022
|
+
attachment: {
|
|
4023
|
+
type: getAttachmentType(file.type),
|
|
4024
|
+
data: "",
|
|
4025
|
+
mimeType: file.type,
|
|
4026
|
+
filename: file.name
|
|
4027
|
+
},
|
|
4028
|
+
status: "processing"
|
|
4029
|
+
}
|
|
4030
|
+
]);
|
|
4031
|
+
try {
|
|
4032
|
+
let attachment;
|
|
4033
|
+
if (processAttachmentProp) {
|
|
4034
|
+
attachment = await processAttachmentProp(file);
|
|
4035
|
+
} else {
|
|
4036
|
+
const data = await fileToBase64(file);
|
|
4037
|
+
attachment = {
|
|
4038
|
+
type: getAttachmentType(file.type),
|
|
4039
|
+
data,
|
|
4040
|
+
mimeType: file.type,
|
|
4041
|
+
filename: file.name
|
|
4042
|
+
};
|
|
4043
|
+
}
|
|
4044
|
+
setPendingAttachments(
|
|
4045
|
+
(prev) => prev.map(
|
|
4046
|
+
(att) => att.id === id ? { ...att, status: "ready", attachment } : att
|
|
4047
|
+
)
|
|
4048
|
+
);
|
|
4049
|
+
} catch (error) {
|
|
4050
|
+
setPendingAttachments(
|
|
4051
|
+
(prev) => prev.map(
|
|
4052
|
+
(att) => att.id === id ? {
|
|
4053
|
+
...att,
|
|
4054
|
+
status: "error",
|
|
4055
|
+
error: "Failed to process file"
|
|
4056
|
+
} : att
|
|
4057
|
+
)
|
|
4058
|
+
);
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
},
|
|
4062
|
+
[attachmentsEnabled, maxFileSize, isFileTypeAllowed, processAttachmentProp]
|
|
4063
|
+
);
|
|
4064
|
+
const handleInputChange = React8.useCallback(
|
|
4065
|
+
(e) => {
|
|
4066
|
+
handleFileSelect(e.target.files);
|
|
4067
|
+
if (fileInputRef.current) {
|
|
4068
|
+
fileInputRef.current.value = "";
|
|
4069
|
+
}
|
|
4070
|
+
},
|
|
4071
|
+
[handleFileSelect]
|
|
4072
|
+
);
|
|
4073
|
+
const removePendingAttachment = React8.useCallback((id) => {
|
|
4074
|
+
setPendingAttachments((prev) => {
|
|
4075
|
+
const att = prev.find((a) => a.id === id);
|
|
4076
|
+
if (att) {
|
|
4077
|
+
URL.revokeObjectURL(att.previewUrl);
|
|
4078
|
+
}
|
|
4079
|
+
return prev.filter((a) => a.id !== id);
|
|
4080
|
+
});
|
|
4081
|
+
}, []);
|
|
4082
|
+
const handleSubmit = React8.useCallback(() => {
|
|
4083
|
+
const hasContent = input.trim();
|
|
4084
|
+
const hasAttachments = pendingAttachments.some(
|
|
4085
|
+
(att) => att.status === "ready"
|
|
4086
|
+
);
|
|
4087
|
+
if (!hasContent && !hasAttachments || isLoading) return;
|
|
4088
|
+
const attachments = pendingAttachments.filter((att) => att.status === "ready").map((att) => att.attachment);
|
|
4089
|
+
onSendMessage(input, attachments.length > 0 ? attachments : void 0);
|
|
4090
|
+
pendingAttachments.forEach((att) => URL.revokeObjectURL(att.previewUrl));
|
|
4091
|
+
setPendingAttachments([]);
|
|
4092
|
+
setInput("");
|
|
4093
|
+
}, [input, isLoading, onSendMessage, pendingAttachments]);
|
|
4094
|
+
const handleSuggestionClick = React8.useCallback(
|
|
4095
|
+
(suggestion) => {
|
|
4096
|
+
onSendMessage(suggestion);
|
|
4097
|
+
},
|
|
4098
|
+
[onSendMessage]
|
|
4099
|
+
);
|
|
4100
|
+
const acceptString = allowedFileTypes.join(",");
|
|
4101
|
+
showRecentChats ? recentThreads.slice(0, maxRecentChats) : [];
|
|
4102
|
+
recentThreads.length > maxRecentChats;
|
|
4103
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4104
|
+
"div",
|
|
4105
|
+
{
|
|
4106
|
+
className: cn(
|
|
4107
|
+
"flex flex-1 flex-col items-center justify-center px-4 py-8 overflow-auto",
|
|
4108
|
+
classNames.root
|
|
4109
|
+
),
|
|
4110
|
+
children: [
|
|
4111
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4112
|
+
"div",
|
|
3246
4113
|
{
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
onApprove: (permissionLevel) => onApproveToolExecution?.(
|
|
3251
|
-
tool.id,
|
|
3252
|
-
void 0,
|
|
3253
|
-
permissionLevel
|
|
4114
|
+
className: cn(
|
|
4115
|
+
"flex flex-col items-center text-center mb-8",
|
|
4116
|
+
classNames.hero
|
|
3254
4117
|
),
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
buttonClassName: followUpButtonClassName
|
|
3268
|
-
}
|
|
3269
|
-
)
|
|
3270
|
-
] })
|
|
3271
|
-
] });
|
|
3272
|
-
}
|
|
3273
|
-
function AttachmentPreview({ attachment }) {
|
|
3274
|
-
const [expanded, setExpanded] = React8__namespace.useState(false);
|
|
3275
|
-
if (attachment.type !== "image") {
|
|
3276
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-lg border bg-muted/50 px-3 py-2 text-sm", children: [
|
|
3277
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-muted-foreground", children: attachment.type }),
|
|
3278
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: attachment.filename || "Attachment" })
|
|
3279
|
-
] });
|
|
3280
|
-
}
|
|
3281
|
-
let src;
|
|
3282
|
-
if (attachment.url) {
|
|
3283
|
-
src = attachment.url;
|
|
3284
|
-
} else if (attachment.data) {
|
|
3285
|
-
src = attachment.data.startsWith("data:") ? attachment.data : `data:${attachment.mimeType};base64,${attachment.data}`;
|
|
3286
|
-
} else {
|
|
3287
|
-
return null;
|
|
3288
|
-
}
|
|
3289
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3290
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3291
|
-
"button",
|
|
3292
|
-
{
|
|
3293
|
-
type: "button",
|
|
3294
|
-
onClick: () => setExpanded(true),
|
|
3295
|
-
className: "relative rounded-lg overflow-hidden border bg-muted/50 hover:opacity-90 transition-opacity",
|
|
3296
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3297
|
-
"img",
|
|
3298
|
-
{
|
|
3299
|
-
src,
|
|
3300
|
-
alt: attachment.filename || "Image",
|
|
3301
|
-
className: "max-w-[200px] max-h-[150px] object-cover"
|
|
4118
|
+
children: [
|
|
4119
|
+
logo ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4120
|
+
"img",
|
|
4121
|
+
{
|
|
4122
|
+
src: logo,
|
|
4123
|
+
alt: "Logo",
|
|
4124
|
+
className: "size-12 rounded-lg object-contain mb-4"
|
|
4125
|
+
}
|
|
4126
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "h-12 w-auto" }) }),
|
|
4127
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-semibold text-foreground mb-2", children: title }),
|
|
4128
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: subtitle })
|
|
4129
|
+
]
|
|
3302
4130
|
}
|
|
3303
|
-
)
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
"
|
|
3314
|
-
|
|
3315
|
-
src,
|
|
3316
|
-
alt: attachment.filename || "Image (expanded)",
|
|
3317
|
-
className: "max-w-full max-h-full object-contain rounded-lg"
|
|
3318
|
-
}
|
|
3319
|
-
),
|
|
3320
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3321
|
-
"button",
|
|
3322
|
-
{
|
|
3323
|
-
type: "button",
|
|
3324
|
-
className: "absolute top-2 right-2 bg-white/90 rounded-full p-2 hover:bg-white transition-colors",
|
|
3325
|
-
onClick: (e) => {
|
|
3326
|
-
e.stopPropagation();
|
|
3327
|
-
setExpanded(false);
|
|
3328
|
-
},
|
|
3329
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4131
|
+
),
|
|
4132
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full max-w-lg mb-6", classNames.input), children: [
|
|
4133
|
+
pendingAttachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 p-2 mb-2 bg-muted/30 rounded-lg", children: pendingAttachments.map((att) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
4134
|
+
att.attachment.type === "image" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4135
|
+
"img",
|
|
4136
|
+
{
|
|
4137
|
+
src: att.previewUrl,
|
|
4138
|
+
alt: att.file.name,
|
|
4139
|
+
className: "w-16 h-16 object-cover rounded-lg border"
|
|
4140
|
+
}
|
|
4141
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-16 h-16 bg-muted rounded-lg border flex flex-col items-center justify-center p-1", children: [
|
|
4142
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3330
4143
|
"svg",
|
|
3331
4144
|
{
|
|
3332
|
-
className: "w-
|
|
4145
|
+
className: "w-6 h-6 text-muted-foreground",
|
|
3333
4146
|
fill: "none",
|
|
3334
4147
|
viewBox: "0 0 24 24",
|
|
3335
4148
|
stroke: "currentColor",
|
|
3336
|
-
strokeWidth: 2,
|
|
3337
4149
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3338
4150
|
"path",
|
|
3339
4151
|
{
|
|
3340
4152
|
strokeLinecap: "round",
|
|
3341
4153
|
strokeLinejoin: "round",
|
|
3342
|
-
|
|
4154
|
+
strokeWidth: 1.5,
|
|
4155
|
+
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
3343
4156
|
}
|
|
3344
4157
|
)
|
|
3345
4158
|
}
|
|
3346
|
-
)
|
|
4159
|
+
),
|
|
4160
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground truncate w-full text-center mt-1", children: att.file.name.length > 10 ? att.file.name.slice(0, 8) + "..." : att.file.name })
|
|
4161
|
+
] }),
|
|
4162
|
+
att.status === "processing" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-background/80 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: "dots", size: "sm" }) }),
|
|
4163
|
+
att.status === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-destructive/20 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive text-xs", children: "Error" }) }),
|
|
4164
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4165
|
+
"button",
|
|
4166
|
+
{
|
|
4167
|
+
onClick: () => removePendingAttachment(att.id),
|
|
4168
|
+
className: "absolute -top-1.5 -right-1.5 bg-destructive text-destructive-foreground rounded-full p-0.5 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
4169
|
+
type: "button",
|
|
4170
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(XIcon2, { className: "w-3 h-3" })
|
|
4171
|
+
}
|
|
4172
|
+
)
|
|
4173
|
+
] }, att.id)) }),
|
|
4174
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4175
|
+
PromptInput,
|
|
4176
|
+
{
|
|
4177
|
+
value: input,
|
|
4178
|
+
onValueChange: setInput,
|
|
4179
|
+
isLoading,
|
|
4180
|
+
onSubmit: handleSubmit,
|
|
4181
|
+
children: [
|
|
4182
|
+
/* @__PURE__ */ jsxRuntime.jsx(PromptInputTextarea, { placeholder }),
|
|
4183
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PromptInputActions, { className: "flex justify-between", children: [
|
|
4184
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4185
|
+
PromptInputAction,
|
|
4186
|
+
{
|
|
4187
|
+
tooltip: attachmentsEnabled ? "Attach files" : attachmentsDisabledTooltip,
|
|
4188
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4189
|
+
"label",
|
|
4190
|
+
{
|
|
4191
|
+
htmlFor: fileInputId,
|
|
4192
|
+
className: cn(
|
|
4193
|
+
"flex h-8 w-8 items-center justify-center rounded-2xl",
|
|
4194
|
+
attachmentsEnabled ? "hover:bg-secondary-foreground/10 cursor-pointer" : "opacity-50 cursor-not-allowed"
|
|
4195
|
+
),
|
|
4196
|
+
children: [
|
|
4197
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4198
|
+
"input",
|
|
4199
|
+
{
|
|
4200
|
+
ref: fileInputRef,
|
|
4201
|
+
type: "file",
|
|
4202
|
+
multiple: true,
|
|
4203
|
+
accept: acceptString,
|
|
4204
|
+
onChange: handleInputChange,
|
|
4205
|
+
className: "hidden",
|
|
4206
|
+
id: fileInputId,
|
|
4207
|
+
disabled: !attachmentsEnabled
|
|
4208
|
+
}
|
|
4209
|
+
),
|
|
4210
|
+
/* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { className: "text-primary size-5" })
|
|
4211
|
+
]
|
|
4212
|
+
}
|
|
4213
|
+
)
|
|
4214
|
+
}
|
|
4215
|
+
) }),
|
|
4216
|
+
/* @__PURE__ */ jsxRuntime.jsx(PromptInputAction, { tooltip: isLoading ? "Stop" : "Send", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4217
|
+
Button,
|
|
4218
|
+
{
|
|
4219
|
+
size: "sm",
|
|
4220
|
+
variant: "destructive",
|
|
4221
|
+
className: "rounded-full size-9",
|
|
4222
|
+
onClick: onStop,
|
|
4223
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(StopIcon, { className: "h-4 w-4" })
|
|
4224
|
+
}
|
|
4225
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4226
|
+
Button,
|
|
4227
|
+
{
|
|
4228
|
+
size: "sm",
|
|
4229
|
+
className: "rounded-full size-9",
|
|
4230
|
+
onClick: handleSubmit,
|
|
4231
|
+
disabled: !input.trim() && !pendingAttachments.some((att) => att.status === "ready"),
|
|
4232
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ArrowUpIcon, { className: "h-4 w-4" })
|
|
4233
|
+
}
|
|
4234
|
+
) })
|
|
4235
|
+
] })
|
|
4236
|
+
]
|
|
3347
4237
|
}
|
|
3348
4238
|
)
|
|
3349
|
-
] })
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
4239
|
+
] }),
|
|
4240
|
+
suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4241
|
+
"div",
|
|
4242
|
+
{
|
|
4243
|
+
className: cn("w-full max-w-lg mb-6 px-3", classNames.suggestions),
|
|
4244
|
+
children: [
|
|
4245
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-medium text-muted-foreground mb-2", children: suggestionsLabel }),
|
|
4246
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "", children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4247
|
+
"button",
|
|
4248
|
+
{
|
|
4249
|
+
type: "button",
|
|
4250
|
+
onClick: () => handleSuggestionClick(suggestion),
|
|
4251
|
+
className: "group w-full cursor-pointer font-medium text-left py-2 text-sm hover:text-foreground text-foreground/70 transition-colors flex items-center gap-2",
|
|
4252
|
+
children: [
|
|
4253
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: suggestion }),
|
|
4254
|
+
/* @__PURE__ */ jsxRuntime.jsx(ArrowUpRightIcon, { className: "size-4 opacity-0 translate-y-1 group-hover:opacity-[0.6] group-hover:translate-y-0 transition-all duration-200" })
|
|
4255
|
+
]
|
|
4256
|
+
},
|
|
4257
|
+
index
|
|
4258
|
+
)) })
|
|
4259
|
+
]
|
|
4260
|
+
}
|
|
4261
|
+
)
|
|
4262
|
+
]
|
|
4263
|
+
}
|
|
4264
|
+
);
|
|
3353
4265
|
}
|
|
3354
|
-
var
|
|
3355
|
-
var
|
|
3356
|
-
function
|
|
4266
|
+
var DEFAULT_MAX_FILE_SIZE2 = 5 * 1024 * 1024;
|
|
4267
|
+
var DEFAULT_ALLOWED_TYPES2 = ["image/*", "application/pdf"];
|
|
4268
|
+
function getAttachmentType2(mimeType) {
|
|
3357
4269
|
if (mimeType.startsWith("image/")) return "image";
|
|
3358
4270
|
if (mimeType.startsWith("audio/")) return "audio";
|
|
3359
4271
|
if (mimeType.startsWith("video/")) return "video";
|
|
3360
4272
|
return "file";
|
|
3361
4273
|
}
|
|
3362
|
-
function
|
|
4274
|
+
function fileToBase642(file) {
|
|
3363
4275
|
return new Promise((resolve, reject) => {
|
|
3364
4276
|
const reader = new FileReader();
|
|
3365
4277
|
reader.onload = () => {
|
|
@@ -3373,7 +4285,7 @@ function fileToBase64(file) {
|
|
|
3373
4285
|
reader.readAsDataURL(file);
|
|
3374
4286
|
});
|
|
3375
4287
|
}
|
|
3376
|
-
function
|
|
4288
|
+
function generateAttachmentId2() {
|
|
3377
4289
|
return `att_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
3378
4290
|
}
|
|
3379
4291
|
function Chat({
|
|
@@ -3388,6 +4300,11 @@ function Chat({
|
|
|
3388
4300
|
title,
|
|
3389
4301
|
// Header
|
|
3390
4302
|
showHeader = false,
|
|
4303
|
+
header,
|
|
4304
|
+
threadPicker,
|
|
4305
|
+
// Deprecated header props (backwards compat)
|
|
4306
|
+
logo,
|
|
4307
|
+
name,
|
|
3391
4308
|
onClose,
|
|
3392
4309
|
// Appearance
|
|
3393
4310
|
showPoweredBy = true,
|
|
@@ -3397,14 +4314,20 @@ function Chat({
|
|
|
3397
4314
|
loaderVariant = "typing",
|
|
3398
4315
|
fontSize = "sm",
|
|
3399
4316
|
// Attachments
|
|
3400
|
-
maxFileSize =
|
|
3401
|
-
allowedFileTypes =
|
|
4317
|
+
maxFileSize = DEFAULT_MAX_FILE_SIZE2,
|
|
4318
|
+
allowedFileTypes = DEFAULT_ALLOWED_TYPES2,
|
|
3402
4319
|
attachmentsEnabled = true,
|
|
3403
4320
|
attachmentsDisabledTooltip = "Attachments not supported by this model",
|
|
3404
4321
|
processAttachment: processAttachmentProp,
|
|
3405
4322
|
// Suggestions
|
|
3406
4323
|
suggestions = [],
|
|
3407
4324
|
onSuggestionClick,
|
|
4325
|
+
// Welcome Screen
|
|
4326
|
+
welcome,
|
|
4327
|
+
recentThreads = [],
|
|
4328
|
+
onSelectThread,
|
|
4329
|
+
onDeleteThread,
|
|
4330
|
+
onViewMoreThreads,
|
|
3408
4331
|
// Tool Executions
|
|
3409
4332
|
isProcessing = false,
|
|
3410
4333
|
registeredTools,
|
|
@@ -3455,7 +4378,7 @@ function Chat({
|
|
|
3455
4378
|
console.warn(`File type ${file.type} is not allowed`);
|
|
3456
4379
|
continue;
|
|
3457
4380
|
}
|
|
3458
|
-
const id =
|
|
4381
|
+
const id = generateAttachmentId2();
|
|
3459
4382
|
const previewUrl = URL.createObjectURL(file);
|
|
3460
4383
|
setPendingAttachments((prev) => [
|
|
3461
4384
|
...prev,
|
|
@@ -3464,7 +4387,7 @@ function Chat({
|
|
|
3464
4387
|
file,
|
|
3465
4388
|
previewUrl,
|
|
3466
4389
|
attachment: {
|
|
3467
|
-
type:
|
|
4390
|
+
type: getAttachmentType2(file.type),
|
|
3468
4391
|
data: "",
|
|
3469
4392
|
mimeType: file.type,
|
|
3470
4393
|
filename: file.name
|
|
@@ -3477,9 +4400,9 @@ function Chat({
|
|
|
3477
4400
|
if (processAttachmentProp) {
|
|
3478
4401
|
attachment = await processAttachmentProp(file);
|
|
3479
4402
|
} else {
|
|
3480
|
-
const data = await
|
|
4403
|
+
const data = await fileToBase642(file);
|
|
3481
4404
|
attachment = {
|
|
3482
|
-
type:
|
|
4405
|
+
type: getAttachmentType2(file.type),
|
|
3483
4406
|
data,
|
|
3484
4407
|
mimeType: file.type,
|
|
3485
4408
|
filename: file.name
|
|
@@ -3572,6 +4495,8 @@ function Chat({
|
|
|
3572
4495
|
[onSuggestionClick, onSendMessage]
|
|
3573
4496
|
);
|
|
3574
4497
|
const acceptString = allowedFileTypes.join(",");
|
|
4498
|
+
const showWelcome = messages.length === 0 && welcome !== false;
|
|
4499
|
+
const welcomeConfig = typeof welcome === "object" ? welcome : void 0;
|
|
3575
4500
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3576
4501
|
"div",
|
|
3577
4502
|
{
|
|
@@ -3588,240 +4513,275 @@ function Chat({
|
|
|
3588
4513
|
showHeader && (renderHeader ? renderHeader() : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3589
4514
|
ChatHeader,
|
|
3590
4515
|
{
|
|
4516
|
+
logo: header?.logo ?? logo,
|
|
4517
|
+
name: header?.name ?? name,
|
|
3591
4518
|
title,
|
|
3592
|
-
|
|
4519
|
+
threadPicker,
|
|
4520
|
+
onClose: header?.onClose ?? onClose,
|
|
3593
4521
|
className: classNames.header
|
|
3594
4522
|
}
|
|
3595
4523
|
)),
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
}
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
4524
|
+
showWelcome ? (
|
|
4525
|
+
/* Welcome Screen (centered input) */
|
|
4526
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4527
|
+
ChatWelcome,
|
|
4528
|
+
{
|
|
4529
|
+
config: welcomeConfig,
|
|
4530
|
+
suggestions,
|
|
4531
|
+
recentThreads,
|
|
4532
|
+
onSendMessage: (msg, attachments) => onSendMessage?.(msg, attachments),
|
|
4533
|
+
onSelectThread,
|
|
4534
|
+
onDeleteThread,
|
|
4535
|
+
onViewMoreThreads,
|
|
4536
|
+
isLoading,
|
|
4537
|
+
onStop,
|
|
4538
|
+
placeholder,
|
|
4539
|
+
attachmentsEnabled,
|
|
4540
|
+
attachmentsDisabledTooltip,
|
|
4541
|
+
maxFileSize,
|
|
4542
|
+
allowedFileTypes,
|
|
4543
|
+
processAttachment: processAttachmentProp
|
|
4544
|
+
}
|
|
4545
|
+
)
|
|
4546
|
+
) : (
|
|
4547
|
+
/* Normal Chat UI (messages + input at bottom) */
|
|
4548
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
4549
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4550
|
+
ChatContainerRoot,
|
|
4551
|
+
{
|
|
4552
|
+
className: cn("relative flex-1", classNames.container),
|
|
4553
|
+
children: [
|
|
4554
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4555
|
+
ChatContainerContent,
|
|
4556
|
+
{
|
|
4557
|
+
className: cn("gap-4 p-4", classNames.messageList),
|
|
4558
|
+
children: [
|
|
4559
|
+
messages.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-8 text-center text-muted-foreground", children: welcomeMessage || "Send a message to start the conversation" }),
|
|
4560
|
+
messages.map((message, index) => {
|
|
4561
|
+
const isLastMessage = index === messages.length - 1;
|
|
4562
|
+
const isEmptyAssistant = message.role === "assistant" && !message.content?.trim();
|
|
4563
|
+
const hasToolCalls = message.tool_calls && message.tool_calls.length > 0;
|
|
4564
|
+
const hasToolExecutions = message.toolExecutions && message.toolExecutions.length > 0;
|
|
4565
|
+
const hasPendingApprovals = message.toolExecutions?.some(
|
|
4566
|
+
(exec) => exec.approvalStatus === "required"
|
|
4567
|
+
);
|
|
4568
|
+
if (isEmptyAssistant) {
|
|
4569
|
+
if (hasToolCalls || hasToolExecutions) ; else if (isLastMessage && hasPendingApprovals) ; else if (isLastMessage && isLoading && !isProcessing) {
|
|
4570
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Message, { className: "flex gap-2", children: [
|
|
4571
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4572
|
+
MessageAvatar,
|
|
4573
|
+
{
|
|
4574
|
+
src: assistantAvatar.src || "",
|
|
4575
|
+
alt: "Assistant",
|
|
4576
|
+
fallback: assistantAvatar.fallback,
|
|
4577
|
+
fallbackIcon: !assistantAvatar.src ? /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
|
|
4578
|
+
className: "bg-background"
|
|
4579
|
+
}
|
|
4580
|
+
),
|
|
4581
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: loaderVariant, size: "sm" }) })
|
|
4582
|
+
] }, message.id);
|
|
4583
|
+
} else {
|
|
4584
|
+
return null;
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
const savedExecutions = message.metadata?.toolExecutions;
|
|
4588
|
+
const messageToolExecutions = message.toolExecutions || savedExecutions;
|
|
4589
|
+
const messageWithExecutions = messageToolExecutions ? { ...message, toolExecutions: messageToolExecutions } : message;
|
|
4590
|
+
const handleFollowUpClick = (question) => {
|
|
4591
|
+
if (onSuggestionClick) {
|
|
4592
|
+
onSuggestionClick(question);
|
|
4593
|
+
} else {
|
|
4594
|
+
onSendMessage?.(question);
|
|
4595
|
+
}
|
|
4596
|
+
};
|
|
4597
|
+
return renderMessage ? /* @__PURE__ */ jsxRuntime.jsx(React8__namespace.default.Fragment, { children: renderMessage(messageWithExecutions, index) }, message.id) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4598
|
+
DefaultMessage,
|
|
4599
|
+
{
|
|
4600
|
+
message: messageWithExecutions,
|
|
4601
|
+
userAvatar,
|
|
4602
|
+
assistantAvatar,
|
|
4603
|
+
showUserAvatar,
|
|
4604
|
+
userMessageClassName: classNames.userMessage,
|
|
4605
|
+
assistantMessageClassName: classNames.assistantMessage,
|
|
4606
|
+
size: fontSize,
|
|
4607
|
+
isLastMessage,
|
|
4608
|
+
isLoading,
|
|
4609
|
+
registeredTools,
|
|
4610
|
+
toolRenderers,
|
|
4611
|
+
onApproveToolExecution,
|
|
4612
|
+
onRejectToolExecution,
|
|
4613
|
+
showFollowUps,
|
|
4614
|
+
onFollowUpClick: handleFollowUpClick,
|
|
4615
|
+
followUpClassName,
|
|
4616
|
+
followUpButtonClassName
|
|
4617
|
+
},
|
|
4618
|
+
message.id
|
|
4619
|
+
);
|
|
4620
|
+
}),
|
|
4621
|
+
isProcessing && /* @__PURE__ */ jsxRuntime.jsxs(Message, { className: "flex gap-2", children: [
|
|
3686
4622
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3687
4623
|
MessageAvatar,
|
|
3688
4624
|
{
|
|
3689
4625
|
src: assistantAvatar?.src || "",
|
|
3690
4626
|
alt: "Assistant",
|
|
3691
4627
|
fallback: assistantAvatar?.fallback || "AI",
|
|
3692
|
-
className: "
|
|
4628
|
+
fallbackIcon: !assistantAvatar?.src ? /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
|
|
4629
|
+
className: "bg-background"
|
|
3693
4630
|
}
|
|
3694
4631
|
),
|
|
3695
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
src: att.previewUrl,
|
|
3722
|
-
alt: att.file.name,
|
|
3723
|
-
className: "w-16 h-16 object-cover rounded-lg border"
|
|
3724
|
-
}
|
|
3725
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-16 h-16 bg-muted rounded-lg border flex flex-col items-center justify-center p-1", children: [
|
|
3726
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3727
|
-
"svg",
|
|
3728
|
-
{
|
|
3729
|
-
className: "w-6 h-6 text-muted-foreground",
|
|
3730
|
-
fill: "none",
|
|
3731
|
-
viewBox: "0 0 24 24",
|
|
3732
|
-
stroke: "currentColor",
|
|
3733
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3734
|
-
"path",
|
|
3735
|
-
{
|
|
3736
|
-
strokeLinecap: "round",
|
|
3737
|
-
strokeLinejoin: "round",
|
|
3738
|
-
strokeWidth: 1.5,
|
|
3739
|
-
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
4632
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg bg-muted px-4 py-2 flex items-center gap-2", children: [
|
|
4633
|
+
/* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: "dots", size: "sm" }),
|
|
4634
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-muted-foreground", children: "Continuing..." })
|
|
4635
|
+
] })
|
|
4636
|
+
] }),
|
|
4637
|
+
isLoading && !isProcessing && (() => {
|
|
4638
|
+
const lastMessage = messages[messages.length - 1];
|
|
4639
|
+
if (lastMessage?.role === "user") {
|
|
4640
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Message, { className: "flex gap-2", children: [
|
|
4641
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4642
|
+
MessageAvatar,
|
|
4643
|
+
{
|
|
4644
|
+
src: assistantAvatar?.src || "",
|
|
4645
|
+
alt: "Assistant",
|
|
4646
|
+
fallback: assistantAvatar?.fallback || "AI",
|
|
4647
|
+
fallbackIcon: !assistantAvatar?.src ? /* @__PURE__ */ jsxRuntime.jsx(copilot_sdk_logo_default, { className: "size-5" }) : void 0,
|
|
4648
|
+
className: "bg-background"
|
|
4649
|
+
}
|
|
4650
|
+
),
|
|
4651
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-muted px-4 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: loaderVariant, size: "sm" }) })
|
|
4652
|
+
] });
|
|
4653
|
+
}
|
|
4654
|
+
return null;
|
|
4655
|
+
})(),
|
|
4656
|
+
/* @__PURE__ */ jsxRuntime.jsx(ChatContainerScrollAnchor, {})
|
|
4657
|
+
]
|
|
3740
4658
|
}
|
|
3741
|
-
)
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3749
|
-
"button",
|
|
4659
|
+
),
|
|
4660
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-4 bottom-4", children: /* @__PURE__ */ jsxRuntime.jsx(ScrollButton, { className: "shadow-sm" }) })
|
|
4661
|
+
]
|
|
4662
|
+
}
|
|
4663
|
+
),
|
|
4664
|
+
suggestions.length > 0 && !isLoading && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4665
|
+
Suggestions,
|
|
3750
4666
|
{
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3754
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(XIcon2, { className: "w-3 h-3" })
|
|
4667
|
+
suggestions,
|
|
4668
|
+
onSuggestionClick: handleSuggestionClick,
|
|
4669
|
+
className: classNames.suggestions
|
|
3755
4670
|
}
|
|
3756
|
-
)
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3770
|
-
PromptInputAction,
|
|
4671
|
+
),
|
|
4672
|
+
renderInput ? renderInput() : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("p-2 pt-0", classNames.input), children: [
|
|
4673
|
+
pendingAttachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2 p-2 mb-2 bg-muted/30 rounded-lg", children: pendingAttachments.map((att) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group", children: [
|
|
4674
|
+
att.attachment.type === "image" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4675
|
+
"img",
|
|
4676
|
+
{
|
|
4677
|
+
src: att.previewUrl,
|
|
4678
|
+
alt: att.file.name,
|
|
4679
|
+
className: "w-16 h-16 object-cover rounded-lg border"
|
|
4680
|
+
}
|
|
4681
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-16 h-16 bg-muted rounded-lg border flex flex-col items-center justify-center p-1", children: [
|
|
4682
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4683
|
+
"svg",
|
|
3771
4684
|
{
|
|
3772
|
-
|
|
3773
|
-
|
|
3774
|
-
|
|
4685
|
+
className: "w-6 h-6 text-muted-foreground",
|
|
4686
|
+
fill: "none",
|
|
4687
|
+
viewBox: "0 0 24 24",
|
|
4688
|
+
stroke: "currentColor",
|
|
4689
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4690
|
+
"path",
|
|
3775
4691
|
{
|
|
3776
|
-
|
|
3777
|
-
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
),
|
|
3781
|
-
children: [
|
|
3782
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3783
|
-
"input",
|
|
3784
|
-
{
|
|
3785
|
-
ref: fileInputRef,
|
|
3786
|
-
type: "file",
|
|
3787
|
-
multiple: true,
|
|
3788
|
-
accept: acceptString,
|
|
3789
|
-
onChange: handleInputChange,
|
|
3790
|
-
className: "hidden",
|
|
3791
|
-
id: fileInputId,
|
|
3792
|
-
disabled: !attachmentsEnabled
|
|
3793
|
-
}
|
|
3794
|
-
),
|
|
3795
|
-
/* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { className: "text-primary size-5" })
|
|
3796
|
-
]
|
|
4692
|
+
strokeLinecap: "round",
|
|
4693
|
+
strokeLinejoin: "round",
|
|
4694
|
+
strokeWidth: 1.5,
|
|
4695
|
+
d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
|
3797
4696
|
}
|
|
3798
4697
|
)
|
|
3799
4698
|
}
|
|
3800
|
-
)
|
|
3801
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
|
|
3812
|
-
|
|
3813
|
-
|
|
3814
|
-
|
|
3815
|
-
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
4699
|
+
),
|
|
4700
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground truncate w-full text-center mt-1", children: att.file.name.length > 10 ? att.file.name.slice(0, 8) + "..." : att.file.name })
|
|
4701
|
+
] }),
|
|
4702
|
+
att.status === "processing" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-background/80 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Loader, { variant: "dots", size: "sm" }) }),
|
|
4703
|
+
att.status === "error" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-destructive/20 rounded-lg flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-destructive text-xs", children: "Error" }) }),
|
|
4704
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4705
|
+
"button",
|
|
4706
|
+
{
|
|
4707
|
+
onClick: () => removePendingAttachment(att.id),
|
|
4708
|
+
className: "absolute -top-1.5 -right-1.5 bg-destructive text-destructive-foreground rounded-full p-0.5 opacity-0 group-hover:opacity-100 transition-opacity",
|
|
4709
|
+
type: "button",
|
|
4710
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(XIcon2, { className: "w-3 h-3" })
|
|
4711
|
+
}
|
|
4712
|
+
)
|
|
4713
|
+
] }, att.id)) }),
|
|
4714
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4715
|
+
PromptInput,
|
|
4716
|
+
{
|
|
4717
|
+
value: input,
|
|
4718
|
+
onValueChange: setInput,
|
|
4719
|
+
isLoading,
|
|
4720
|
+
onSubmit: handleSubmit,
|
|
4721
|
+
className: "",
|
|
4722
|
+
children: [
|
|
4723
|
+
/* @__PURE__ */ jsxRuntime.jsx(PromptInputTextarea, { placeholder }),
|
|
4724
|
+
/* @__PURE__ */ jsxRuntime.jsxs(PromptInputActions, { className: "flex justify-between", children: [
|
|
4725
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4726
|
+
PromptInputAction,
|
|
4727
|
+
{
|
|
4728
|
+
tooltip: attachmentsEnabled ? "Attach files" : attachmentsDisabledTooltip,
|
|
4729
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4730
|
+
"label",
|
|
4731
|
+
{
|
|
4732
|
+
htmlFor: fileInputId,
|
|
4733
|
+
className: cn(
|
|
4734
|
+
"flex h-8 w-8 items-center justify-center rounded-2xl",
|
|
4735
|
+
attachmentsEnabled ? "hover:bg-secondary-foreground/10 cursor-pointer" : "opacity-50 cursor-not-allowed"
|
|
4736
|
+
),
|
|
4737
|
+
children: [
|
|
4738
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4739
|
+
"input",
|
|
4740
|
+
{
|
|
4741
|
+
ref: fileInputRef,
|
|
4742
|
+
type: "file",
|
|
4743
|
+
multiple: true,
|
|
4744
|
+
accept: acceptString,
|
|
4745
|
+
onChange: handleInputChange,
|
|
4746
|
+
className: "hidden",
|
|
4747
|
+
id: fileInputId,
|
|
4748
|
+
disabled: !attachmentsEnabled
|
|
4749
|
+
}
|
|
4750
|
+
),
|
|
4751
|
+
/* @__PURE__ */ jsxRuntime.jsx(PlusIcon, { className: "text-primary size-5" })
|
|
4752
|
+
]
|
|
4753
|
+
}
|
|
4754
|
+
)
|
|
4755
|
+
}
|
|
4756
|
+
) }),
|
|
4757
|
+
/* @__PURE__ */ jsxRuntime.jsx(PromptInputAction, { tooltip: isLoading ? "Stop" : "Send", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
4758
|
+
Button,
|
|
4759
|
+
{
|
|
4760
|
+
size: "sm",
|
|
4761
|
+
variant: "destructive",
|
|
4762
|
+
className: "rounded-full size-9",
|
|
4763
|
+
onClick: onStop,
|
|
4764
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(StopIcon, { className: "h-4 w-4" })
|
|
4765
|
+
}
|
|
4766
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
4767
|
+
Button,
|
|
4768
|
+
{
|
|
4769
|
+
size: "sm",
|
|
4770
|
+
className: "rounded-full size-9",
|
|
4771
|
+
onClick: handleSubmit,
|
|
4772
|
+
disabled: !input.trim() && !pendingAttachments.some(
|
|
4773
|
+
(att) => att.status === "ready"
|
|
4774
|
+
),
|
|
4775
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ArrowUpIcon, { className: "h-4 w-4" })
|
|
4776
|
+
}
|
|
4777
|
+
) })
|
|
4778
|
+
] })
|
|
4779
|
+
]
|
|
4780
|
+
}
|
|
4781
|
+
)
|
|
4782
|
+
] })
|
|
4783
|
+
] })
|
|
4784
|
+
)
|
|
3825
4785
|
]
|
|
3826
4786
|
}
|
|
3827
4787
|
);
|
|
@@ -3947,7 +4907,229 @@ function ToolExecutionMessage({
|
|
|
3947
4907
|
] })
|
|
3948
4908
|
] });
|
|
3949
4909
|
}
|
|
4910
|
+
function useInternalThreadManager(config = {}) {
|
|
4911
|
+
const {
|
|
4912
|
+
adapter,
|
|
4913
|
+
saveDebounce = 1e3,
|
|
4914
|
+
autoRestoreLastThread = true,
|
|
4915
|
+
onThreadChange
|
|
4916
|
+
} = config;
|
|
4917
|
+
const threadManagerConfig = {
|
|
4918
|
+
adapter,
|
|
4919
|
+
saveDebounce,
|
|
4920
|
+
autoRestoreLastThread
|
|
4921
|
+
};
|
|
4922
|
+
const threadManager = chunkBN75ZW24_cjs.useThreadManager(threadManagerConfig);
|
|
4923
|
+
const {
|
|
4924
|
+
currentThread,
|
|
4925
|
+
currentThreadId,
|
|
4926
|
+
createThread,
|
|
4927
|
+
switchThread,
|
|
4928
|
+
updateCurrentThread,
|
|
4929
|
+
clearCurrentThread,
|
|
4930
|
+
refreshThreads
|
|
4931
|
+
} = threadManager;
|
|
4932
|
+
const { messages, setMessages, status, isLoading } = chunkBN75ZW24_cjs.useCopilot();
|
|
4933
|
+
const isLoadingMessagesRef = React8.useRef(false);
|
|
4934
|
+
const savingToThreadRef = React8.useRef(null);
|
|
4935
|
+
const lastSavedSnapshotRef = React8.useRef("");
|
|
4936
|
+
const hasInitializedRef = React8.useRef(false);
|
|
4937
|
+
const getMessageSnapshot = React8.useCallback((msgs) => {
|
|
4938
|
+
return msgs.map((m) => {
|
|
4939
|
+
const contentPreview = (m.content ?? "").slice(0, 20);
|
|
4940
|
+
return `${m.id}:${contentPreview}:${m.content?.length ?? 0}`;
|
|
4941
|
+
}).join("|");
|
|
4942
|
+
}, []);
|
|
4943
|
+
const convertToCore = React8.useCallback((msgs) => {
|
|
4944
|
+
return msgs.map((m) => ({
|
|
4945
|
+
id: m.id,
|
|
4946
|
+
role: m.role,
|
|
4947
|
+
content: m.content,
|
|
4948
|
+
created_at: m.createdAt,
|
|
4949
|
+
tool_calls: m.toolCalls,
|
|
4950
|
+
tool_call_id: m.toolCallId,
|
|
4951
|
+
metadata: {
|
|
4952
|
+
attachments: m.attachments,
|
|
4953
|
+
thinking: m.thinking
|
|
4954
|
+
}
|
|
4955
|
+
}));
|
|
4956
|
+
}, []);
|
|
4957
|
+
const handleSwitchThread = React8.useCallback(
|
|
4958
|
+
async (threadId) => {
|
|
4959
|
+
isLoadingMessagesRef.current = true;
|
|
4960
|
+
const thread = await switchThread(threadId);
|
|
4961
|
+
if (thread?.messages) {
|
|
4962
|
+
const uiMessages = thread.messages.map((m) => ({
|
|
4963
|
+
id: m.id,
|
|
4964
|
+
role: m.role,
|
|
4965
|
+
content: m.content ?? "",
|
|
4966
|
+
createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
|
|
4967
|
+
toolCalls: m.tool_calls,
|
|
4968
|
+
toolCallId: m.tool_call_id,
|
|
4969
|
+
attachments: m.metadata?.attachments
|
|
4970
|
+
}));
|
|
4971
|
+
lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
|
|
4972
|
+
savingToThreadRef.current = threadId;
|
|
4973
|
+
setMessages(uiMessages);
|
|
4974
|
+
} else {
|
|
4975
|
+
lastSavedSnapshotRef.current = "";
|
|
4976
|
+
savingToThreadRef.current = threadId;
|
|
4977
|
+
setMessages([]);
|
|
4978
|
+
}
|
|
4979
|
+
onThreadChange?.(threadId);
|
|
4980
|
+
requestAnimationFrame(() => {
|
|
4981
|
+
isLoadingMessagesRef.current = false;
|
|
4982
|
+
});
|
|
4983
|
+
},
|
|
4984
|
+
[switchThread, setMessages, getMessageSnapshot, onThreadChange]
|
|
4985
|
+
);
|
|
4986
|
+
const handleNewThread = React8.useCallback(async () => {
|
|
4987
|
+
isLoadingMessagesRef.current = true;
|
|
4988
|
+
clearCurrentThread();
|
|
4989
|
+
lastSavedSnapshotRef.current = "";
|
|
4990
|
+
savingToThreadRef.current = null;
|
|
4991
|
+
setMessages([]);
|
|
4992
|
+
onThreadChange?.(null);
|
|
4993
|
+
requestAnimationFrame(() => {
|
|
4994
|
+
isLoadingMessagesRef.current = false;
|
|
4995
|
+
});
|
|
4996
|
+
}, [clearCurrentThread, setMessages, onThreadChange]);
|
|
4997
|
+
React8.useEffect(() => {
|
|
4998
|
+
if (hasInitializedRef.current || !currentThread) {
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
5001
|
+
hasInitializedRef.current = true;
|
|
5002
|
+
isLoadingMessagesRef.current = true;
|
|
5003
|
+
if (currentThread.messages && currentThread.messages.length > 0) {
|
|
5004
|
+
const uiMessages = currentThread.messages.map((m) => ({
|
|
5005
|
+
id: m.id,
|
|
5006
|
+
role: m.role,
|
|
5007
|
+
content: m.content ?? "",
|
|
5008
|
+
createdAt: m.created_at ?? /* @__PURE__ */ new Date(),
|
|
5009
|
+
toolCalls: m.tool_calls,
|
|
5010
|
+
toolCallId: m.tool_call_id,
|
|
5011
|
+
attachments: m.metadata?.attachments
|
|
5012
|
+
}));
|
|
5013
|
+
lastSavedSnapshotRef.current = getMessageSnapshot(uiMessages);
|
|
5014
|
+
savingToThreadRef.current = currentThread.id;
|
|
5015
|
+
setMessages(uiMessages);
|
|
5016
|
+
} else {
|
|
5017
|
+
lastSavedSnapshotRef.current = "";
|
|
5018
|
+
savingToThreadRef.current = currentThread.id;
|
|
5019
|
+
}
|
|
5020
|
+
onThreadChange?.(currentThread.id);
|
|
5021
|
+
requestAnimationFrame(() => {
|
|
5022
|
+
isLoadingMessagesRef.current = false;
|
|
5023
|
+
});
|
|
5024
|
+
}, [currentThread, setMessages, getMessageSnapshot, onThreadChange]);
|
|
5025
|
+
React8.useEffect(() => {
|
|
5026
|
+
if (isLoadingMessagesRef.current) {
|
|
5027
|
+
return;
|
|
5028
|
+
}
|
|
5029
|
+
if (status === "streaming" || status === "submitted") {
|
|
5030
|
+
return;
|
|
5031
|
+
}
|
|
5032
|
+
if (messages.length === 0) {
|
|
5033
|
+
return;
|
|
5034
|
+
}
|
|
5035
|
+
const currentSnapshot = getMessageSnapshot(messages);
|
|
5036
|
+
if (currentSnapshot === lastSavedSnapshotRef.current) {
|
|
5037
|
+
return;
|
|
5038
|
+
}
|
|
5039
|
+
const coreMessages = convertToCore(messages);
|
|
5040
|
+
if (!currentThreadId && !savingToThreadRef.current) {
|
|
5041
|
+
savingToThreadRef.current = "creating";
|
|
5042
|
+
createThread({ messages: coreMessages }).then((thread) => {
|
|
5043
|
+
lastSavedSnapshotRef.current = currentSnapshot;
|
|
5044
|
+
savingToThreadRef.current = thread.id;
|
|
5045
|
+
onThreadChange?.(thread.id);
|
|
5046
|
+
});
|
|
5047
|
+
return;
|
|
5048
|
+
}
|
|
5049
|
+
if (savingToThreadRef.current && savingToThreadRef.current !== currentThreadId) {
|
|
5050
|
+
return;
|
|
5051
|
+
}
|
|
5052
|
+
updateCurrentThread({ messages: coreMessages });
|
|
5053
|
+
lastSavedSnapshotRef.current = currentSnapshot;
|
|
5054
|
+
}, [
|
|
5055
|
+
messages,
|
|
5056
|
+
currentThreadId,
|
|
5057
|
+
status,
|
|
5058
|
+
updateCurrentThread,
|
|
5059
|
+
createThread,
|
|
5060
|
+
refreshThreads,
|
|
5061
|
+
getMessageSnapshot,
|
|
5062
|
+
convertToCore,
|
|
5063
|
+
onThreadChange
|
|
5064
|
+
]);
|
|
5065
|
+
const isBusy = isLoading || status === "streaming" || status === "submitted";
|
|
5066
|
+
return {
|
|
5067
|
+
threadManager,
|
|
5068
|
+
handleSwitchThread,
|
|
5069
|
+
handleNewThread,
|
|
5070
|
+
isBusy
|
|
5071
|
+
};
|
|
5072
|
+
}
|
|
5073
|
+
function parsePersistenceConfig(persistence, onThreadChange) {
|
|
5074
|
+
if (!persistence) {
|
|
5075
|
+
return void 0;
|
|
5076
|
+
}
|
|
5077
|
+
if (persistence === true) {
|
|
5078
|
+
return {
|
|
5079
|
+
onThreadChange,
|
|
5080
|
+
autoRestoreLastThread: true
|
|
5081
|
+
};
|
|
5082
|
+
}
|
|
5083
|
+
if ("type" in persistence) {
|
|
5084
|
+
switch (persistence.type) {
|
|
5085
|
+
case "local":
|
|
5086
|
+
return {
|
|
5087
|
+
saveDebounce: persistence.saveDebounce,
|
|
5088
|
+
autoRestoreLastThread: persistence.autoRestoreLastThread ?? true,
|
|
5089
|
+
onThreadChange
|
|
5090
|
+
};
|
|
5091
|
+
case "server":
|
|
5092
|
+
return {
|
|
5093
|
+
adapter: chunk42YQ4ATO_cjs.createServerAdapter({
|
|
5094
|
+
endpoint: persistence.endpoint,
|
|
5095
|
+
headers: persistence.headers
|
|
5096
|
+
}),
|
|
5097
|
+
saveDebounce: persistence.saveDebounce,
|
|
5098
|
+
autoRestoreLastThread: persistence.autoRestoreLastThread ?? true,
|
|
5099
|
+
onThreadChange
|
|
5100
|
+
};
|
|
5101
|
+
case "cloud":
|
|
5102
|
+
console.warn(
|
|
5103
|
+
"[Copilot SDK] Cloud persistence is not yet implemented. Falling back to localStorage."
|
|
5104
|
+
);
|
|
5105
|
+
return {
|
|
5106
|
+
onThreadChange,
|
|
5107
|
+
autoRestoreLastThread: true
|
|
5108
|
+
};
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
5111
|
+
const legacyConfig = persistence;
|
|
5112
|
+
return {
|
|
5113
|
+
adapter: legacyConfig.adapter,
|
|
5114
|
+
saveDebounce: legacyConfig.saveDebounce,
|
|
5115
|
+
autoRestoreLastThread: legacyConfig.autoRestoreLastThread ?? true,
|
|
5116
|
+
onThreadChange
|
|
5117
|
+
};
|
|
5118
|
+
}
|
|
3950
5119
|
function CopilotChat(props) {
|
|
5120
|
+
const {
|
|
5121
|
+
persistence,
|
|
5122
|
+
showThreadPicker = false,
|
|
5123
|
+
onThreadChange,
|
|
5124
|
+
classNames,
|
|
5125
|
+
header,
|
|
5126
|
+
...chatProps
|
|
5127
|
+
} = props;
|
|
5128
|
+
const persistenceConfig = parsePersistenceConfig(persistence, onThreadChange);
|
|
5129
|
+
const threadManagerResult = useInternalThreadManager(
|
|
5130
|
+
persistenceConfig ?? { autoRestoreLastThread: false }
|
|
5131
|
+
);
|
|
5132
|
+
const isPersistenceEnabled = !!persistence;
|
|
3951
5133
|
const {
|
|
3952
5134
|
messages,
|
|
3953
5135
|
isLoading,
|
|
@@ -3957,7 +5139,7 @@ function CopilotChat(props) {
|
|
|
3957
5139
|
approveToolExecution,
|
|
3958
5140
|
rejectToolExecution,
|
|
3959
5141
|
registeredTools
|
|
3960
|
-
} =
|
|
5142
|
+
} = chunkBN75ZW24_cjs.useCopilot();
|
|
3961
5143
|
const toolExecutions = rawToolExecutions.map(
|
|
3962
5144
|
(exec) => ({
|
|
3963
5145
|
id: exec.id,
|
|
@@ -4047,7 +5229,7 @@ function CopilotChat(props) {
|
|
|
4047
5229
|
toolExecutions: messageToolExecutions
|
|
4048
5230
|
};
|
|
4049
5231
|
});
|
|
4050
|
-
const suggestions = visibleMessages.length === 0 &&
|
|
5232
|
+
const suggestions = visibleMessages.length === 0 && chatProps.suggestions?.length ? chatProps.suggestions : [];
|
|
4051
5233
|
const lastMessage = messages[messages.length - 1];
|
|
4052
5234
|
const isInToolFlow = lastMessage?.role === "assistant" && lastMessage.toolCalls?.length;
|
|
4053
5235
|
let isProcessingToolResults = false;
|
|
@@ -4068,20 +5250,70 @@ function CopilotChat(props) {
|
|
|
4068
5250
|
);
|
|
4069
5251
|
isProcessingToolResults = hasCompletedTools && !hasExecutingTools;
|
|
4070
5252
|
}
|
|
5253
|
+
const chatClassNames = classNames ? {
|
|
5254
|
+
root: classNames.root,
|
|
5255
|
+
header: classNames.header,
|
|
5256
|
+
container: classNames.container,
|
|
5257
|
+
messageList: classNames.messageList,
|
|
5258
|
+
userMessage: classNames.userMessage,
|
|
5259
|
+
assistantMessage: classNames.assistantMessage,
|
|
5260
|
+
input: classNames.input,
|
|
5261
|
+
suggestions: classNames.suggestions,
|
|
5262
|
+
footer: classNames.footer
|
|
5263
|
+
} : void 0;
|
|
5264
|
+
const { threadManager, handleSwitchThread, handleNewThread, isBusy } = threadManagerResult;
|
|
5265
|
+
const handleDeleteThread = React8__namespace.default.useCallback(
|
|
5266
|
+
(threadId) => {
|
|
5267
|
+
const isCurrentThread = threadManager.currentThreadId === threadId;
|
|
5268
|
+
threadManager.deleteThread(threadId);
|
|
5269
|
+
if (isCurrentThread) {
|
|
5270
|
+
handleNewThread();
|
|
5271
|
+
}
|
|
5272
|
+
},
|
|
5273
|
+
[threadManager, handleNewThread]
|
|
5274
|
+
);
|
|
5275
|
+
const threadPickerElement = isPersistenceEnabled && showThreadPicker ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5276
|
+
ThreadPicker,
|
|
5277
|
+
{
|
|
5278
|
+
value: threadManager.currentThreadId,
|
|
5279
|
+
threads: threadManager.threads,
|
|
5280
|
+
onSelect: handleSwitchThread,
|
|
5281
|
+
onDeleteThread: handleDeleteThread,
|
|
5282
|
+
onNewThread: handleNewThread,
|
|
5283
|
+
loading: threadManager.isLoading,
|
|
5284
|
+
disabled: isBusy,
|
|
5285
|
+
size: "sm",
|
|
5286
|
+
className: classNames?.threadPicker,
|
|
5287
|
+
buttonClassName: classNames?.threadPickerButton,
|
|
5288
|
+
dropdownClassName: classNames?.threadPickerDropdown,
|
|
5289
|
+
itemClassName: classNames?.threadPickerItem,
|
|
5290
|
+
newButtonClassName: classNames?.threadPickerNewButton
|
|
5291
|
+
}
|
|
5292
|
+
) : void 0;
|
|
5293
|
+
const shouldShowHeader = !!header || showThreadPicker || chatProps.showHeader;
|
|
5294
|
+
const useCustomHeader = chatProps.renderHeader && !header && !showThreadPicker;
|
|
4071
5295
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
4072
5296
|
Chat,
|
|
4073
5297
|
{
|
|
4074
|
-
...
|
|
5298
|
+
...chatProps,
|
|
4075
5299
|
messages: visibleMessages,
|
|
4076
5300
|
onSendMessage: sendMessage,
|
|
4077
5301
|
onStop: stop,
|
|
4078
5302
|
isLoading,
|
|
4079
|
-
showPoweredBy:
|
|
5303
|
+
showPoweredBy: chatProps.showPoweredBy ?? true,
|
|
4080
5304
|
suggestions,
|
|
4081
5305
|
isProcessing: isProcessingToolResults,
|
|
4082
5306
|
onApproveToolExecution: approveToolExecution,
|
|
4083
5307
|
onRejectToolExecution: rejectToolExecution,
|
|
4084
|
-
registeredTools
|
|
5308
|
+
registeredTools,
|
|
5309
|
+
classNames: chatClassNames,
|
|
5310
|
+
header,
|
|
5311
|
+
threadPicker: threadPickerElement,
|
|
5312
|
+
showHeader: shouldShowHeader,
|
|
5313
|
+
renderHeader: useCustomHeader ? chatProps.renderHeader : void 0,
|
|
5314
|
+
recentThreads: isPersistenceEnabled ? threadManager.threads : void 0,
|
|
5315
|
+
onSelectThread: isPersistenceEnabled ? handleSwitchThread : void 0,
|
|
5316
|
+
onDeleteThread: isPersistenceEnabled ? handleDeleteThread : void 0
|
|
4085
5317
|
}
|
|
4086
5318
|
);
|
|
4087
5319
|
}
|
|
@@ -4141,6 +5373,7 @@ exports.Chat = Chat;
|
|
|
4141
5373
|
exports.ChatContainerContent = ChatContainerContent;
|
|
4142
5374
|
exports.ChatContainerRoot = ChatContainerRoot;
|
|
4143
5375
|
exports.ChatContainerScrollAnchor = ChatContainerScrollAnchor;
|
|
5376
|
+
exports.ChatWelcome = ChatWelcome;
|
|
4144
5377
|
exports.CheckIcon = CheckIcon;
|
|
4145
5378
|
exports.ChevronDownIcon = ChevronDownIcon2;
|
|
4146
5379
|
exports.ChevronUpIcon = ChevronUpIcon;
|
|
@@ -4187,6 +5420,9 @@ exports.Source = Source;
|
|
|
4187
5420
|
exports.SourceContent = SourceContent;
|
|
4188
5421
|
exports.SourceTrigger = SourceTrigger;
|
|
4189
5422
|
exports.StopIcon = StopIcon;
|
|
5423
|
+
exports.ThreadCard = ThreadCard;
|
|
5424
|
+
exports.ThreadList = ThreadList;
|
|
5425
|
+
exports.ThreadPicker = ThreadPicker;
|
|
4190
5426
|
exports.ThumbsDownIcon = ThumbsDownIcon2;
|
|
4191
5427
|
exports.ThumbsUpIcon = ThumbsUpIcon2;
|
|
4192
5428
|
exports.ToolExecutionMessage = ToolExecutionMessage;
|