@lssm/module.ai-chat 0.0.0-canary-20251217080011 → 1.41.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/ai-chat.feature.js +1 -93
- package/dist/context/context-builder.js +2 -147
- package/dist/context/file-operations.js +1 -174
- package/dist/context/index.js +1 -5
- package/dist/context/workspace-context.js +2 -123
- package/dist/core/chat-service.js +2 -211
- package/dist/core/conversation-store.js +1 -108
- package/dist/core/index.js +1 -4
- package/dist/index.js +1 -22
- package/dist/presentation/components/ChatContainer.js +1 -62
- package/dist/presentation/components/ChatInput.js +1 -149
- package/dist/presentation/components/ChatMessage.js +1 -135
- package/dist/presentation/components/CodePreview.js +2 -126
- package/dist/presentation/components/ContextIndicator.js +1 -96
- package/dist/presentation/components/ModelPicker.js +1 -197
- package/dist/presentation/components/index.js +1 -8
- package/dist/presentation/hooks/index.js +1 -4
- package/dist/presentation/hooks/useChat.js +1 -171
- package/dist/presentation/hooks/useProviders.js +1 -42
- package/dist/presentation/index.js +1 -12
- package/dist/providers/chat-utilities.js +1 -16
- package/dist/providers/index.js +1 -7
- package/package.json +17 -18
- package/dist/ai-chat.feature.d.ts +0 -11
- package/dist/context/context-builder.d.ts +0 -56
- package/dist/context/file-operations.d.ts +0 -99
- package/dist/context/index.d.ts +0 -4
- package/dist/context/workspace-context.d.ts +0 -116
- package/dist/core/chat-service.d.ts +0 -72
- package/dist/core/conversation-store.d.ts +0 -73
- package/dist/core/index.d.ts +0 -4
- package/dist/core/message-types.d.ts +0 -149
- package/dist/index.d.ts +0 -16
- package/dist/libs/ai-providers/dist/factory.js +0 -225
- package/dist/libs/ai-providers/dist/index.js +0 -4
- package/dist/libs/ai-providers/dist/legacy.js +0 -2
- package/dist/libs/ai-providers/dist/models.js +0 -299
- package/dist/libs/ai-providers/dist/validation.js +0 -60
- package/dist/libs/design-system/dist/_virtual/rolldown_runtime.js +0 -5
- package/dist/libs/design-system/dist/components/atoms/Button.js +0 -33
- package/dist/libs/design-system/dist/components/atoms/Textarea.js +0 -35
- package/dist/libs/design-system/dist/lib/keyboard.js +0 -193
- package/dist/libs/design-system/dist/ui-kit-web/dist/ui/button.js +0 -55
- package/dist/libs/design-system/dist/ui-kit-web/dist/ui/textarea.js +0 -16
- package/dist/libs/design-system/dist/ui-kit-web/dist/ui-kit-core/dist/utils.js +0 -13
- package/dist/libs/ui-kit-web/dist/ui/avatar.js +0 -25
- package/dist/libs/ui-kit-web/dist/ui/badge.js +0 -26
- package/dist/libs/ui-kit-web/dist/ui/scroll-area.js +0 -39
- package/dist/libs/ui-kit-web/dist/ui/select.js +0 -79
- package/dist/libs/ui-kit-web/dist/ui/skeleton.js +0 -14
- package/dist/libs/ui-kit-web/dist/ui/tooltip.js +0 -39
- package/dist/libs/ui-kit-web/dist/ui/utils.js +0 -10
- package/dist/libs/ui-kit-web/dist/ui-kit-core/dist/utils.js +0 -10
- package/dist/presentation/components/ChatContainer.d.ts +0 -20
- package/dist/presentation/components/ChatInput.d.ts +0 -34
- package/dist/presentation/components/ChatMessage.d.ts +0 -23
- package/dist/presentation/components/CodePreview.d.ts +0 -39
- package/dist/presentation/components/ContextIndicator.d.ts +0 -25
- package/dist/presentation/components/ModelPicker.d.ts +0 -38
- package/dist/presentation/components/index.d.ts +0 -7
- package/dist/presentation/hooks/index.d.ts +0 -3
- package/dist/presentation/hooks/useChat.d.ts +0 -66
- package/dist/presentation/hooks/useProviders.d.ts +0 -37
- package/dist/presentation/index.d.ts +0 -10
- package/dist/providers/chat-utilities.d.ts +0 -14
- package/dist/providers/index.d.ts +0 -3
|
@@ -1,135 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../libs/ui-kit-web/dist/ui/utils.js";
|
|
4
|
-
import { Avatar, AvatarFallback } from "../../libs/ui-kit-web/dist/ui/avatar.js";
|
|
5
|
-
import { Skeleton } from "../../libs/ui-kit-web/dist/ui/skeleton.js";
|
|
6
|
-
import { Button$1 } from "../../libs/design-system/dist/components/atoms/Button.js";
|
|
7
|
-
import { CodePreview } from "./CodePreview.js";
|
|
8
|
-
import * as React from "react";
|
|
9
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import { AlertCircle, Bot, Check, Copy, User } from "lucide-react";
|
|
11
|
-
|
|
12
|
-
//#region src/presentation/components/ChatMessage.tsx
|
|
13
|
-
/**
|
|
14
|
-
* Extract code blocks from message content
|
|
15
|
-
*/
|
|
16
|
-
function extractCodeBlocks(content) {
|
|
17
|
-
const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
|
|
18
|
-
const blocks = [];
|
|
19
|
-
let match;
|
|
20
|
-
while ((match = codeBlockRegex.exec(content)) !== null) blocks.push({
|
|
21
|
-
language: match[1] ?? "text",
|
|
22
|
-
code: match[2] ?? "",
|
|
23
|
-
raw: match[0]
|
|
24
|
-
});
|
|
25
|
-
return blocks;
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Render message content with code blocks
|
|
29
|
-
*/
|
|
30
|
-
function MessageContent({ content }) {
|
|
31
|
-
const codeBlocks = extractCodeBlocks(content);
|
|
32
|
-
if (codeBlocks.length === 0) return /* @__PURE__ */ jsx("p", {
|
|
33
|
-
className: "whitespace-pre-wrap",
|
|
34
|
-
children: content
|
|
35
|
-
});
|
|
36
|
-
let remaining = content;
|
|
37
|
-
const parts = [];
|
|
38
|
-
let key = 0;
|
|
39
|
-
for (const block of codeBlocks) {
|
|
40
|
-
const [before, after] = remaining.split(block.raw);
|
|
41
|
-
if (before) parts.push(/* @__PURE__ */ jsx("p", {
|
|
42
|
-
className: "whitespace-pre-wrap",
|
|
43
|
-
children: before.trim()
|
|
44
|
-
}, key++));
|
|
45
|
-
parts.push(/* @__PURE__ */ jsx(CodePreview, {
|
|
46
|
-
code: block.code,
|
|
47
|
-
language: block.language,
|
|
48
|
-
className: "my-2"
|
|
49
|
-
}, key++));
|
|
50
|
-
remaining = after ?? "";
|
|
51
|
-
}
|
|
52
|
-
if (remaining.trim()) parts.push(/* @__PURE__ */ jsx("p", {
|
|
53
|
-
className: "whitespace-pre-wrap",
|
|
54
|
-
children: remaining.trim()
|
|
55
|
-
}, key++));
|
|
56
|
-
return /* @__PURE__ */ jsx(Fragment, { children: parts });
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Chat message component
|
|
60
|
-
*/
|
|
61
|
-
function ChatMessage({ message, className, showCopy = true, showAvatar = true }) {
|
|
62
|
-
const [copied, setCopied] = React.useState(false);
|
|
63
|
-
const isUser = message.role === "user";
|
|
64
|
-
const isError = message.status === "error";
|
|
65
|
-
const isStreaming = message.status === "streaming";
|
|
66
|
-
const handleCopy = React.useCallback(async () => {
|
|
67
|
-
await navigator.clipboard.writeText(message.content);
|
|
68
|
-
setCopied(true);
|
|
69
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
70
|
-
}, [message.content]);
|
|
71
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
72
|
-
className: cn("group flex gap-3", isUser && "flex-row-reverse", className),
|
|
73
|
-
children: [showAvatar && /* @__PURE__ */ jsx(Avatar, {
|
|
74
|
-
className: "h-8 w-8 shrink-0",
|
|
75
|
-
children: /* @__PURE__ */ jsx(AvatarFallback, {
|
|
76
|
-
className: cn(isUser ? "bg-primary text-primary-foreground" : "bg-muted"),
|
|
77
|
-
children: isUser ? /* @__PURE__ */ jsx(User, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Bot, { className: "h-4 w-4" })
|
|
78
|
-
})
|
|
79
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
80
|
-
className: cn("flex max-w-[80%] flex-col gap-1", isUser && "items-end"),
|
|
81
|
-
children: [
|
|
82
|
-
/* @__PURE__ */ jsx("div", {
|
|
83
|
-
className: cn("rounded-2xl px-4 py-2", isUser ? "bg-primary text-primary-foreground" : "bg-muted text-foreground", isError && "border-destructive bg-destructive/10 border"),
|
|
84
|
-
children: isError && message.error ? /* @__PURE__ */ jsxs("div", {
|
|
85
|
-
className: "flex items-start gap-2",
|
|
86
|
-
children: [/* @__PURE__ */ jsx(AlertCircle, { className: "text-destructive mt-0.5 h-4 w-4 shrink-0" }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
|
|
87
|
-
className: "text-destructive font-medium",
|
|
88
|
-
children: message.error.code
|
|
89
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
90
|
-
className: "text-muted-foreground text-sm",
|
|
91
|
-
children: message.error.message
|
|
92
|
-
})] })]
|
|
93
|
-
}) : isStreaming && !message.content ? /* @__PURE__ */ jsxs("div", {
|
|
94
|
-
className: "flex flex-col gap-2",
|
|
95
|
-
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-48" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-32" })]
|
|
96
|
-
}) : /* @__PURE__ */ jsx(MessageContent, { content: message.content })
|
|
97
|
-
}),
|
|
98
|
-
/* @__PURE__ */ jsxs("div", {
|
|
99
|
-
className: cn("flex items-center gap-2 text-xs", "text-muted-foreground opacity-0 transition-opacity", "group-hover:opacity-100"),
|
|
100
|
-
children: [
|
|
101
|
-
/* @__PURE__ */ jsx("span", { children: new Date(message.createdAt).toLocaleTimeString([], {
|
|
102
|
-
hour: "2-digit",
|
|
103
|
-
minute: "2-digit"
|
|
104
|
-
}) }),
|
|
105
|
-
message.usage && /* @__PURE__ */ jsxs("span", { children: [message.usage.inputTokens + message.usage.outputTokens, " tokens"] }),
|
|
106
|
-
showCopy && !isUser && message.content && /* @__PURE__ */ jsx(Button$1, {
|
|
107
|
-
variant: "ghost",
|
|
108
|
-
size: "sm",
|
|
109
|
-
className: "h-6 w-6 p-0",
|
|
110
|
-
onPress: handleCopy,
|
|
111
|
-
"aria-label": copied ? "Copied" : "Copy message",
|
|
112
|
-
children: copied ? /* @__PURE__ */ jsx(Check, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3 w-3" })
|
|
113
|
-
})
|
|
114
|
-
]
|
|
115
|
-
}),
|
|
116
|
-
message.reasoning && /* @__PURE__ */ jsxs("details", {
|
|
117
|
-
className: "text-muted-foreground mt-2 text-sm",
|
|
118
|
-
children: [/* @__PURE__ */ jsx("summary", {
|
|
119
|
-
className: "cursor-pointer hover:underline",
|
|
120
|
-
children: "View reasoning"
|
|
121
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
122
|
-
className: "bg-muted mt-1 rounded-md p-2",
|
|
123
|
-
children: /* @__PURE__ */ jsx("p", {
|
|
124
|
-
className: "whitespace-pre-wrap",
|
|
125
|
-
children: message.reasoning
|
|
126
|
-
})
|
|
127
|
-
})]
|
|
128
|
-
})
|
|
129
|
-
]
|
|
130
|
-
})]
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
//#endregion
|
|
135
|
-
export { ChatMessage };
|
|
1
|
+
"use client";import{CodePreview as e}from"./CodePreview.js";import*as t from"react";import{cn as n}from"@lssm/lib.ui-kit-web/ui/utils";import{Fragment as r,jsx as i,jsxs as a}from"react/jsx-runtime";import{Avatar as o,AvatarFallback as s}from"@lssm/lib.ui-kit-web/ui/avatar";import{Skeleton as c}from"@lssm/lib.ui-kit-web/ui/skeleton";import{AlertCircle as l,Bot as u,Check as d,Copy as f,User as p}from"lucide-react";import{Button as m}from"@lssm/lib.design-system";function h(e){let t=/```(\w+)?\n([\s\S]*?)```/g,n=[],r;for(;(r=t.exec(e))!==null;)n.push({language:r[1]??`text`,code:r[2]??``,raw:r[0]});return n}function g({content:t}){let n=h(t);if(n.length===0)return i(`p`,{className:`whitespace-pre-wrap`,children:t});let a=t,o=[],s=0;for(let t of n){let[n,r]=a.split(t.raw);n&&o.push(i(`p`,{className:`whitespace-pre-wrap`,children:n.trim()},s++)),o.push(i(e,{code:t.code,language:t.language,className:`my-2`},s++)),a=r??``}return a.trim()&&o.push(i(`p`,{className:`whitespace-pre-wrap`,children:a.trim()},s++)),i(r,{children:o})}function _({message:e,className:r,showCopy:h=!0,showAvatar:_=!0}){let[v,y]=t.useState(!1),b=e.role===`user`,x=e.status===`error`,S=e.status===`streaming`,C=t.useCallback(async()=>{await navigator.clipboard.writeText(e.content),y(!0),setTimeout(()=>y(!1),2e3)},[e.content]);return a(`div`,{className:n(`group flex gap-3`,b&&`flex-row-reverse`,r),children:[_&&i(o,{className:`h-8 w-8 shrink-0`,children:i(s,{className:n(b?`bg-primary text-primary-foreground`:`bg-muted`),children:i(b?p:u,{className:`h-4 w-4`})})}),a(`div`,{className:n(`flex max-w-[80%] flex-col gap-1`,b&&`items-end`),children:[i(`div`,{className:n(`rounded-2xl px-4 py-2`,b?`bg-primary text-primary-foreground`:`bg-muted text-foreground`,x&&`border-destructive bg-destructive/10 border`),children:x&&e.error?a(`div`,{className:`flex items-start gap-2`,children:[i(l,{className:`text-destructive mt-0.5 h-4 w-4 shrink-0`}),a(`div`,{children:[i(`p`,{className:`text-destructive font-medium`,children:e.error.code}),i(`p`,{className:`text-muted-foreground text-sm`,children:e.error.message})]})]}):S&&!e.content?a(`div`,{className:`flex flex-col gap-2`,children:[i(c,{className:`h-4 w-48`}),i(c,{className:`h-4 w-32`})]}):i(g,{content:e.content})}),a(`div`,{className:n(`flex items-center gap-2 text-xs`,`text-muted-foreground opacity-0 transition-opacity`,`group-hover:opacity-100`),children:[i(`span`,{children:new Date(e.createdAt).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`})}),e.usage&&a(`span`,{children:[e.usage.inputTokens+e.usage.outputTokens,` tokens`]}),h&&!b&&e.content&&i(m,{variant:`ghost`,size:`sm`,className:`h-6 w-6 p-0`,onPress:C,"aria-label":v?`Copied`:`Copy message`,children:i(v?d:f,{className:`h-3 w-3`})})]}),e.reasoning&&a(`details`,{className:`text-muted-foreground mt-2 text-sm`,children:[i(`summary`,{className:`cursor-pointer hover:underline`,children:`View reasoning`}),i(`div`,{className:`bg-muted mt-1 rounded-md p-2`,children:i(`p`,{className:`whitespace-pre-wrap`,children:e.reasoning})})]})]})]})}export{_ as ChatMessage};
|
|
@@ -1,126 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../libs/ui-kit-web/dist/ui/utils.js";
|
|
4
|
-
import { Button$1 } from "../../libs/design-system/dist/components/atoms/Button.js";
|
|
5
|
-
import * as React from "react";
|
|
6
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
import { Check, Copy, Download, Play } from "lucide-react";
|
|
8
|
-
|
|
9
|
-
//#region src/presentation/components/CodePreview.tsx
|
|
10
|
-
/**
|
|
11
|
-
* Language display names
|
|
12
|
-
*/
|
|
13
|
-
const LANGUAGE_NAMES = {
|
|
14
|
-
ts: "TypeScript",
|
|
15
|
-
tsx: "TypeScript (React)",
|
|
16
|
-
typescript: "TypeScript",
|
|
17
|
-
js: "JavaScript",
|
|
18
|
-
jsx: "JavaScript (React)",
|
|
19
|
-
javascript: "JavaScript",
|
|
20
|
-
json: "JSON",
|
|
21
|
-
md: "Markdown",
|
|
22
|
-
yaml: "YAML",
|
|
23
|
-
yml: "YAML",
|
|
24
|
-
bash: "Bash",
|
|
25
|
-
sh: "Shell",
|
|
26
|
-
sql: "SQL",
|
|
27
|
-
py: "Python",
|
|
28
|
-
python: "Python",
|
|
29
|
-
go: "Go",
|
|
30
|
-
rust: "Rust",
|
|
31
|
-
rs: "Rust"
|
|
32
|
-
};
|
|
33
|
-
/**
|
|
34
|
-
* Code preview component with syntax highlighting placeholder
|
|
35
|
-
*/
|
|
36
|
-
function CodePreview({ code, language = "text", filename, className, showCopy = true, showExecute = false, onExecute, showDownload = false, maxHeight = 400 }) {
|
|
37
|
-
const [copied, setCopied] = React.useState(false);
|
|
38
|
-
const displayLanguage = LANGUAGE_NAMES[language.toLowerCase()] ?? language;
|
|
39
|
-
const lines = code.split("\n");
|
|
40
|
-
const handleCopy = React.useCallback(async () => {
|
|
41
|
-
await navigator.clipboard.writeText(code);
|
|
42
|
-
setCopied(true);
|
|
43
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
44
|
-
}, [code]);
|
|
45
|
-
const handleDownload = React.useCallback(() => {
|
|
46
|
-
const blob = new Blob([code], { type: "text/plain" });
|
|
47
|
-
const url = URL.createObjectURL(blob);
|
|
48
|
-
const a = document.createElement("a");
|
|
49
|
-
a.href = url;
|
|
50
|
-
a.download = filename ?? `code.${language}`;
|
|
51
|
-
document.body.appendChild(a);
|
|
52
|
-
a.click();
|
|
53
|
-
document.body.removeChild(a);
|
|
54
|
-
URL.revokeObjectURL(url);
|
|
55
|
-
}, [
|
|
56
|
-
code,
|
|
57
|
-
filename,
|
|
58
|
-
language
|
|
59
|
-
]);
|
|
60
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
61
|
-
className: cn("overflow-hidden rounded-lg border", "bg-muted/50", className),
|
|
62
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
63
|
-
className: cn("flex items-center justify-between px-3 py-1.5", "border-b bg-muted/80"),
|
|
64
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
65
|
-
className: "flex items-center gap-2 text-sm",
|
|
66
|
-
children: [filename && /* @__PURE__ */ jsx("span", {
|
|
67
|
-
className: "text-foreground font-mono",
|
|
68
|
-
children: filename
|
|
69
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
70
|
-
className: "text-muted-foreground",
|
|
71
|
-
children: displayLanguage
|
|
72
|
-
})]
|
|
73
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
74
|
-
className: "flex items-center gap-1",
|
|
75
|
-
children: [
|
|
76
|
-
showExecute && onExecute && /* @__PURE__ */ jsx(Button$1, {
|
|
77
|
-
variant: "ghost",
|
|
78
|
-
size: "sm",
|
|
79
|
-
onPress: () => onExecute(code),
|
|
80
|
-
className: "h-7 w-7 p-0",
|
|
81
|
-
"aria-label": "Execute code",
|
|
82
|
-
children: /* @__PURE__ */ jsx(Play, { className: "h-3.5 w-3.5" })
|
|
83
|
-
}),
|
|
84
|
-
showDownload && /* @__PURE__ */ jsx(Button$1, {
|
|
85
|
-
variant: "ghost",
|
|
86
|
-
size: "sm",
|
|
87
|
-
onPress: handleDownload,
|
|
88
|
-
className: "h-7 w-7 p-0",
|
|
89
|
-
"aria-label": "Download code",
|
|
90
|
-
children: /* @__PURE__ */ jsx(Download, { className: "h-3.5 w-3.5" })
|
|
91
|
-
}),
|
|
92
|
-
showCopy && /* @__PURE__ */ jsx(Button$1, {
|
|
93
|
-
variant: "ghost",
|
|
94
|
-
size: "sm",
|
|
95
|
-
onPress: handleCopy,
|
|
96
|
-
className: "h-7 w-7 p-0",
|
|
97
|
-
"aria-label": copied ? "Copied" : "Copy code",
|
|
98
|
-
children: copied ? /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5 text-green-500" }) : /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" })
|
|
99
|
-
})
|
|
100
|
-
]
|
|
101
|
-
})]
|
|
102
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
103
|
-
className: "overflow-auto",
|
|
104
|
-
style: { maxHeight },
|
|
105
|
-
children: /* @__PURE__ */ jsx("pre", {
|
|
106
|
-
className: "p-3",
|
|
107
|
-
children: /* @__PURE__ */ jsx("code", {
|
|
108
|
-
className: "text-sm",
|
|
109
|
-
children: lines.map((line, i) => /* @__PURE__ */ jsxs("div", {
|
|
110
|
-
className: "flex",
|
|
111
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
112
|
-
className: "text-muted-foreground mr-4 select-none text-right w-8",
|
|
113
|
-
children: i + 1
|
|
114
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
115
|
-
className: "flex-1",
|
|
116
|
-
children: line || " "
|
|
117
|
-
})]
|
|
118
|
-
}, i))
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
})]
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
//#endregion
|
|
126
|
-
export { CodePreview };
|
|
1
|
+
"use client";import*as e from"react";import{cn as t}from"@lssm/lib.ui-kit-web/ui/utils";import{jsx as n,jsxs as r}from"react/jsx-runtime";import{Check as i,Copy as a,Download as o,Play as s}from"lucide-react";import{Button as c}from"@lssm/lib.design-system";const l={ts:`TypeScript`,tsx:`TypeScript (React)`,typescript:`TypeScript`,js:`JavaScript`,jsx:`JavaScript (React)`,javascript:`JavaScript`,json:`JSON`,md:`Markdown`,yaml:`YAML`,yml:`YAML`,bash:`Bash`,sh:`Shell`,sql:`SQL`,py:`Python`,python:`Python`,go:`Go`,rust:`Rust`,rs:`Rust`};function u({code:u,language:d=`text`,filename:f,className:p,showCopy:m=!0,showExecute:h=!1,onExecute:g,showDownload:_=!1,maxHeight:v=400}){let[y,b]=e.useState(!1),x=l[d.toLowerCase()]??d,S=u.split(`
|
|
2
|
+
`),C=e.useCallback(async()=>{await navigator.clipboard.writeText(u),b(!0),setTimeout(()=>b(!1),2e3)},[u]),w=e.useCallback(()=>{let e=new Blob([u],{type:`text/plain`}),t=URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=f??`code.${d}`,document.body.appendChild(n),n.click(),document.body.removeChild(n),URL.revokeObjectURL(t)},[u,f,d]);return r(`div`,{className:t(`overflow-hidden rounded-lg border`,`bg-muted/50`,p),children:[r(`div`,{className:t(`flex items-center justify-between px-3 py-1.5`,`border-b bg-muted/80`),children:[r(`div`,{className:`flex items-center gap-2 text-sm`,children:[f&&n(`span`,{className:`text-foreground font-mono`,children:f}),n(`span`,{className:`text-muted-foreground`,children:x})]}),r(`div`,{className:`flex items-center gap-1`,children:[h&&g&&n(c,{variant:`ghost`,size:`sm`,onPress:()=>g(u),className:`h-7 w-7 p-0`,"aria-label":`Execute code`,children:n(s,{className:`h-3.5 w-3.5`})}),_&&n(c,{variant:`ghost`,size:`sm`,onPress:w,className:`h-7 w-7 p-0`,"aria-label":`Download code`,children:n(o,{className:`h-3.5 w-3.5`})}),m&&n(c,{variant:`ghost`,size:`sm`,onPress:C,className:`h-7 w-7 p-0`,"aria-label":y?`Copied`:`Copy code`,children:y?n(i,{className:`h-3.5 w-3.5 text-green-500`}):n(a,{className:`h-3.5 w-3.5`})})]})]}),n(`div`,{className:`overflow-auto`,style:{maxHeight:v},children:n(`pre`,{className:`p-3`,children:n(`code`,{className:`text-sm`,children:S.map((e,t)=>r(`div`,{className:`flex`,children:[n(`span`,{className:`text-muted-foreground mr-4 select-none text-right w-8`,children:t+1}),n(`span`,{className:`flex-1`,children:e||` `})]},t))})})})]})}export{u as CodePreview};
|
|
@@ -1,96 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { cn } from "../../libs/ui-kit-web/dist/ui/utils.js";
|
|
4
|
-
import { Badge } from "../../libs/ui-kit-web/dist/ui/badge.js";
|
|
5
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../libs/ui-kit-web/dist/ui/tooltip.js";
|
|
6
|
-
import "react";
|
|
7
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
-
import { FileCode, FolderOpen, Info, Zap } from "lucide-react";
|
|
9
|
-
|
|
10
|
-
//#region src/presentation/components/ContextIndicator.tsx
|
|
11
|
-
/**
|
|
12
|
-
* Indicator showing active workspace context
|
|
13
|
-
*/
|
|
14
|
-
function ContextIndicator({ summary, active = false, className, showDetails = true }) {
|
|
15
|
-
if (!summary && !active) return /* @__PURE__ */ jsxs("div", {
|
|
16
|
-
className: cn("flex items-center gap-1.5 text-sm", "text-muted-foreground", className),
|
|
17
|
-
children: [/* @__PURE__ */ jsx(Info, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", { children: "No workspace context" })]
|
|
18
|
-
});
|
|
19
|
-
const content = /* @__PURE__ */ jsxs("div", {
|
|
20
|
-
className: cn("flex items-center gap-2", active ? "text-foreground" : "text-muted-foreground", className),
|
|
21
|
-
children: [/* @__PURE__ */ jsxs(Badge, {
|
|
22
|
-
variant: active ? "default" : "secondary",
|
|
23
|
-
className: "flex items-center gap-1",
|
|
24
|
-
children: [/* @__PURE__ */ jsx(Zap, { className: "h-3 w-3" }), "Context"]
|
|
25
|
-
}), summary && showDetails && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
26
|
-
className: "flex items-center gap-1 text-xs",
|
|
27
|
-
children: [/* @__PURE__ */ jsx(FolderOpen, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ jsx("span", { children: summary.name })]
|
|
28
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
29
|
-
className: "flex items-center gap-1 text-xs",
|
|
30
|
-
children: [/* @__PURE__ */ jsx(FileCode, { className: "h-3.5 w-3.5" }), /* @__PURE__ */ jsxs("span", { children: [summary.specs.total, " specs"] })]
|
|
31
|
-
})] })]
|
|
32
|
-
});
|
|
33
|
-
if (!summary) return content;
|
|
34
|
-
return /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsxs(Tooltip, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
|
|
35
|
-
asChild: true,
|
|
36
|
-
children: content
|
|
37
|
-
}), /* @__PURE__ */ jsx(TooltipContent, {
|
|
38
|
-
side: "bottom",
|
|
39
|
-
className: "max-w-[300px]",
|
|
40
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
41
|
-
className: "flex flex-col gap-2 text-sm",
|
|
42
|
-
children: [
|
|
43
|
-
/* @__PURE__ */ jsx("div", {
|
|
44
|
-
className: "font-medium",
|
|
45
|
-
children: summary.name
|
|
46
|
-
}),
|
|
47
|
-
/* @__PURE__ */ jsx("div", {
|
|
48
|
-
className: "text-muted-foreground text-xs",
|
|
49
|
-
children: summary.path
|
|
50
|
-
}),
|
|
51
|
-
/* @__PURE__ */ jsx("div", {
|
|
52
|
-
className: "border-t pt-2",
|
|
53
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
54
|
-
className: "grid grid-cols-2 gap-1 text-xs",
|
|
55
|
-
children: [
|
|
56
|
-
/* @__PURE__ */ jsx("span", { children: "Commands:" }),
|
|
57
|
-
/* @__PURE__ */ jsx("span", {
|
|
58
|
-
className: "text-right",
|
|
59
|
-
children: summary.specs.commands
|
|
60
|
-
}),
|
|
61
|
-
/* @__PURE__ */ jsx("span", { children: "Queries:" }),
|
|
62
|
-
/* @__PURE__ */ jsx("span", {
|
|
63
|
-
className: "text-right",
|
|
64
|
-
children: summary.specs.queries
|
|
65
|
-
}),
|
|
66
|
-
/* @__PURE__ */ jsx("span", { children: "Events:" }),
|
|
67
|
-
/* @__PURE__ */ jsx("span", {
|
|
68
|
-
className: "text-right",
|
|
69
|
-
children: summary.specs.events
|
|
70
|
-
}),
|
|
71
|
-
/* @__PURE__ */ jsx("span", { children: "Presentations:" }),
|
|
72
|
-
/* @__PURE__ */ jsx("span", {
|
|
73
|
-
className: "text-right",
|
|
74
|
-
children: summary.specs.presentations
|
|
75
|
-
})
|
|
76
|
-
]
|
|
77
|
-
})
|
|
78
|
-
}),
|
|
79
|
-
/* @__PURE__ */ jsxs("div", {
|
|
80
|
-
className: "border-t pt-2 text-xs",
|
|
81
|
-
children: [
|
|
82
|
-
/* @__PURE__ */ jsxs("span", { children: [summary.files.total, " files"] }),
|
|
83
|
-
/* @__PURE__ */ jsx("span", {
|
|
84
|
-
className: "mx-1",
|
|
85
|
-
children: "•"
|
|
86
|
-
}),
|
|
87
|
-
/* @__PURE__ */ jsxs("span", { children: [summary.files.specFiles, " spec files"] })
|
|
88
|
-
]
|
|
89
|
-
})
|
|
90
|
-
]
|
|
91
|
-
})
|
|
92
|
-
})] }) });
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
//#endregion
|
|
96
|
-
export { ContextIndicator };
|
|
1
|
+
"use client";import"react";import{cn as e}from"@lssm/lib.ui-kit-web/ui/utils";import{Fragment as t,jsx as n,jsxs as r}from"react/jsx-runtime";import{FileCode as i,FolderOpen as a,Info as o,Zap as s}from"lucide-react";import{Badge as c}from"@lssm/lib.ui-kit-web/ui/badge";import{Tooltip as l,TooltipContent as u,TooltipProvider as d,TooltipTrigger as f}from"@lssm/lib.ui-kit-web/ui/tooltip";function p({summary:p,active:m=!1,className:h,showDetails:g=!0}){if(!p&&!m)return r(`div`,{className:e(`flex items-center gap-1.5 text-sm`,`text-muted-foreground`,h),children:[n(o,{className:`h-4 w-4`}),n(`span`,{children:`No workspace context`})]});let _=r(`div`,{className:e(`flex items-center gap-2`,m?`text-foreground`:`text-muted-foreground`,h),children:[r(c,{variant:m?`default`:`secondary`,className:`flex items-center gap-1`,children:[n(s,{className:`h-3 w-3`}),`Context`]}),p&&g&&r(t,{children:[r(`div`,{className:`flex items-center gap-1 text-xs`,children:[n(a,{className:`h-3.5 w-3.5`}),n(`span`,{children:p.name})]}),r(`div`,{className:`flex items-center gap-1 text-xs`,children:[n(i,{className:`h-3.5 w-3.5`}),r(`span`,{children:[p.specs.total,` specs`]})]})]})]});return p?n(d,{children:r(l,{children:[n(f,{asChild:!0,children:_}),n(u,{side:`bottom`,className:`max-w-[300px]`,children:r(`div`,{className:`flex flex-col gap-2 text-sm`,children:[n(`div`,{className:`font-medium`,children:p.name}),n(`div`,{className:`text-muted-foreground text-xs`,children:p.path}),n(`div`,{className:`border-t pt-2`,children:r(`div`,{className:`grid grid-cols-2 gap-1 text-xs`,children:[n(`span`,{children:`Commands:`}),n(`span`,{className:`text-right`,children:p.specs.commands}),n(`span`,{children:`Queries:`}),n(`span`,{className:`text-right`,children:p.specs.queries}),n(`span`,{children:`Events:`}),n(`span`,{className:`text-right`,children:p.specs.events}),n(`span`,{children:`Presentations:`}),n(`span`,{className:`text-right`,children:p.specs.presentations})]})}),r(`div`,{className:`border-t pt-2 text-xs`,children:[r(`span`,{children:[p.files.total,` files`]}),n(`span`,{className:`mx-1`,children:`•`}),r(`span`,{children:[p.files.specFiles,` spec files`]})]})]})})]})}):_}export{p as ContextIndicator};
|
|
@@ -1,197 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { getModelsForProvider } from "../../libs/ai-providers/dist/models.js";
|
|
4
|
-
import "../../libs/ai-providers/dist/index.js";
|
|
5
|
-
import { cn } from "../../libs/ui-kit-web/dist/ui/utils.js";
|
|
6
|
-
import { Button$1 } from "../../libs/design-system/dist/components/atoms/Button.js";
|
|
7
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../libs/ui-kit-web/dist/ui/select.js";
|
|
8
|
-
import { Badge } from "../../libs/ui-kit-web/dist/ui/badge.js";
|
|
9
|
-
import * as React from "react";
|
|
10
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
import { Bot, Cloud, Cpu, Sparkles } from "lucide-react";
|
|
12
|
-
|
|
13
|
-
//#region src/presentation/components/ModelPicker.tsx
|
|
14
|
-
const PROVIDER_ICONS = {
|
|
15
|
-
ollama: /* @__PURE__ */ jsx(Cpu, { className: "h-4 w-4" }),
|
|
16
|
-
openai: /* @__PURE__ */ jsx(Bot, { className: "h-4 w-4" }),
|
|
17
|
-
anthropic: /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4" }),
|
|
18
|
-
mistral: /* @__PURE__ */ jsx(Cloud, { className: "h-4 w-4" }),
|
|
19
|
-
gemini: /* @__PURE__ */ jsx(Sparkles, { className: "h-4 w-4" })
|
|
20
|
-
};
|
|
21
|
-
const PROVIDER_NAMES = {
|
|
22
|
-
ollama: "Ollama (Local)",
|
|
23
|
-
openai: "OpenAI",
|
|
24
|
-
anthropic: "Anthropic",
|
|
25
|
-
mistral: "Mistral",
|
|
26
|
-
gemini: "Google Gemini"
|
|
27
|
-
};
|
|
28
|
-
const MODE_BADGES = {
|
|
29
|
-
local: {
|
|
30
|
-
label: "Local",
|
|
31
|
-
variant: "secondary"
|
|
32
|
-
},
|
|
33
|
-
byok: {
|
|
34
|
-
label: "BYOK",
|
|
35
|
-
variant: "outline"
|
|
36
|
-
},
|
|
37
|
-
managed: {
|
|
38
|
-
label: "Managed",
|
|
39
|
-
variant: "default"
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
/**
|
|
43
|
-
* Model picker component for selecting AI provider and model
|
|
44
|
-
*/
|
|
45
|
-
function ModelPicker({ value, onChange, availableProviders, className, compact = false }) {
|
|
46
|
-
const providers = availableProviders ?? [
|
|
47
|
-
{
|
|
48
|
-
provider: "ollama",
|
|
49
|
-
available: true,
|
|
50
|
-
mode: "local"
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
provider: "openai",
|
|
54
|
-
available: true,
|
|
55
|
-
mode: "byok"
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
provider: "anthropic",
|
|
59
|
-
available: true,
|
|
60
|
-
mode: "byok"
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
provider: "mistral",
|
|
64
|
-
available: true,
|
|
65
|
-
mode: "byok"
|
|
66
|
-
},
|
|
67
|
-
{
|
|
68
|
-
provider: "gemini",
|
|
69
|
-
available: true,
|
|
70
|
-
mode: "byok"
|
|
71
|
-
}
|
|
72
|
-
];
|
|
73
|
-
const models = getModelsForProvider(value.provider);
|
|
74
|
-
const selectedModel = models.find((m) => m.id === value.model);
|
|
75
|
-
const handleProviderChange = React.useCallback((providerName) => {
|
|
76
|
-
const provider = providerName;
|
|
77
|
-
const providerInfo = providers.find((p) => p.provider === provider);
|
|
78
|
-
onChange({
|
|
79
|
-
provider,
|
|
80
|
-
model: getModelsForProvider(provider)[0]?.id ?? "",
|
|
81
|
-
mode: providerInfo?.mode ?? "byok"
|
|
82
|
-
});
|
|
83
|
-
}, [onChange, providers]);
|
|
84
|
-
const handleModelChange = React.useCallback((modelId) => {
|
|
85
|
-
onChange({
|
|
86
|
-
...value,
|
|
87
|
-
model: modelId
|
|
88
|
-
});
|
|
89
|
-
}, [onChange, value]);
|
|
90
|
-
if (compact) return /* @__PURE__ */ jsxs("div", {
|
|
91
|
-
className: cn("flex items-center gap-2", className),
|
|
92
|
-
children: [/* @__PURE__ */ jsxs(Select, {
|
|
93
|
-
value: value.provider,
|
|
94
|
-
onValueChange: handleProviderChange,
|
|
95
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
96
|
-
className: "w-[140px]",
|
|
97
|
-
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
98
|
-
}), /* @__PURE__ */ jsx(SelectContent, { children: providers.map((p) => /* @__PURE__ */ jsx(SelectItem, {
|
|
99
|
-
value: p.provider,
|
|
100
|
-
disabled: !p.available,
|
|
101
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
102
|
-
className: "flex items-center gap-2",
|
|
103
|
-
children: [PROVIDER_ICONS[p.provider], /* @__PURE__ */ jsx("span", { children: PROVIDER_NAMES[p.provider] })]
|
|
104
|
-
})
|
|
105
|
-
}, p.provider)) })]
|
|
106
|
-
}), /* @__PURE__ */ jsxs(Select, {
|
|
107
|
-
value: value.model,
|
|
108
|
-
onValueChange: handleModelChange,
|
|
109
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
110
|
-
className: "w-[160px]",
|
|
111
|
-
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
112
|
-
}), /* @__PURE__ */ jsx(SelectContent, { children: models.map((m) => /* @__PURE__ */ jsx(SelectItem, {
|
|
113
|
-
value: m.id,
|
|
114
|
-
children: m.name
|
|
115
|
-
}, m.id)) })]
|
|
116
|
-
})]
|
|
117
|
-
});
|
|
118
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
119
|
-
className: cn("flex flex-col gap-3", className),
|
|
120
|
-
children: [
|
|
121
|
-
/* @__PURE__ */ jsxs("div", {
|
|
122
|
-
className: "flex flex-col gap-1.5",
|
|
123
|
-
children: [/* @__PURE__ */ jsx("label", {
|
|
124
|
-
className: "text-sm font-medium",
|
|
125
|
-
children: "Provider"
|
|
126
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
127
|
-
className: "flex flex-wrap gap-2",
|
|
128
|
-
children: providers.map((p) => /* @__PURE__ */ jsxs(Button$1, {
|
|
129
|
-
variant: value.provider === p.provider ? "default" : "outline",
|
|
130
|
-
size: "sm",
|
|
131
|
-
onPress: () => p.available && handleProviderChange(p.provider),
|
|
132
|
-
disabled: !p.available,
|
|
133
|
-
className: cn(!p.available && "opacity-50"),
|
|
134
|
-
children: [
|
|
135
|
-
PROVIDER_ICONS[p.provider],
|
|
136
|
-
/* @__PURE__ */ jsx("span", { children: PROVIDER_NAMES[p.provider] }),
|
|
137
|
-
/* @__PURE__ */ jsx(Badge, {
|
|
138
|
-
variant: MODE_BADGES[p.mode].variant,
|
|
139
|
-
className: "ml-1",
|
|
140
|
-
children: MODE_BADGES[p.mode].label
|
|
141
|
-
})
|
|
142
|
-
]
|
|
143
|
-
}, p.provider))
|
|
144
|
-
})]
|
|
145
|
-
}),
|
|
146
|
-
/* @__PURE__ */ jsxs("div", {
|
|
147
|
-
className: "flex flex-col gap-1.5",
|
|
148
|
-
children: [/* @__PURE__ */ jsx("label", {
|
|
149
|
-
className: "text-sm font-medium",
|
|
150
|
-
children: "Model"
|
|
151
|
-
}), /* @__PURE__ */ jsxs(Select, {
|
|
152
|
-
value: value.model,
|
|
153
|
-
onValueChange: handleModelChange,
|
|
154
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a model" }) }), /* @__PURE__ */ jsx(SelectContent, { children: models.map((m) => /* @__PURE__ */ jsx(SelectItem, {
|
|
155
|
-
value: m.id,
|
|
156
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
157
|
-
className: "flex items-center gap-2",
|
|
158
|
-
children: [
|
|
159
|
-
/* @__PURE__ */ jsx("span", { children: m.name }),
|
|
160
|
-
/* @__PURE__ */ jsxs("span", {
|
|
161
|
-
className: "text-muted-foreground text-xs",
|
|
162
|
-
children: [Math.round(m.contextWindow / 1e3), "K"]
|
|
163
|
-
}),
|
|
164
|
-
m.capabilities.vision && /* @__PURE__ */ jsx(Badge, {
|
|
165
|
-
variant: "outline",
|
|
166
|
-
className: "text-xs",
|
|
167
|
-
children: "Vision"
|
|
168
|
-
}),
|
|
169
|
-
m.capabilities.reasoning && /* @__PURE__ */ jsx(Badge, {
|
|
170
|
-
variant: "outline",
|
|
171
|
-
className: "text-xs",
|
|
172
|
-
children: "Reasoning"
|
|
173
|
-
})
|
|
174
|
-
]
|
|
175
|
-
})
|
|
176
|
-
}, m.id)) })]
|
|
177
|
-
})]
|
|
178
|
-
}),
|
|
179
|
-
selectedModel && /* @__PURE__ */ jsxs("div", {
|
|
180
|
-
className: "text-muted-foreground flex flex-wrap gap-2 text-xs",
|
|
181
|
-
children: [
|
|
182
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
183
|
-
"Context: ",
|
|
184
|
-
Math.round(selectedModel.contextWindow / 1e3),
|
|
185
|
-
"K tokens"
|
|
186
|
-
] }),
|
|
187
|
-
selectedModel.capabilities.vision && /* @__PURE__ */ jsx("span", { children: "• Vision" }),
|
|
188
|
-
selectedModel.capabilities.tools && /* @__PURE__ */ jsx("span", { children: "• Tools" }),
|
|
189
|
-
selectedModel.capabilities.reasoning && /* @__PURE__ */ jsx("span", { children: "• Reasoning" })
|
|
190
|
-
]
|
|
191
|
-
})
|
|
192
|
-
]
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
//#endregion
|
|
197
|
-
export { ModelPicker };
|
|
1
|
+
"use client";import{getModelsForProvider as e}from"@lssm/lib.ai-providers";import*as t from"react";import{cn as n}from"@lssm/lib.ui-kit-web/ui/utils";import{jsx as r,jsxs as i}from"react/jsx-runtime";import{Bot as a,Cloud as o,Cpu as s,Sparkles as c}from"lucide-react";import{Button as l}from"@lssm/lib.design-system";import{Select as u,SelectContent as d,SelectItem as f,SelectTrigger as p,SelectValue as m}from"@lssm/lib.ui-kit-web/ui/select";import{Badge as h}from"@lssm/lib.ui-kit-web/ui/badge";const g={ollama:r(s,{className:`h-4 w-4`}),openai:r(a,{className:`h-4 w-4`}),anthropic:r(c,{className:`h-4 w-4`}),mistral:r(o,{className:`h-4 w-4`}),gemini:r(c,{className:`h-4 w-4`})},_={ollama:`Ollama (Local)`,openai:`OpenAI`,anthropic:`Anthropic`,mistral:`Mistral`,gemini:`Google Gemini`},v={local:{label:`Local`,variant:`secondary`},byok:{label:`BYOK`,variant:`outline`},managed:{label:`Managed`,variant:`default`}};function y({value:a,onChange:o,availableProviders:s,className:c,compact:y=!1}){let b=s??[{provider:`ollama`,available:!0,mode:`local`},{provider:`openai`,available:!0,mode:`byok`},{provider:`anthropic`,available:!0,mode:`byok`},{provider:`mistral`,available:!0,mode:`byok`},{provider:`gemini`,available:!0,mode:`byok`}],x=e(a.provider),S=x.find(e=>e.id===a.model),C=t.useCallback(t=>{let n=t,r=b.find(e=>e.provider===n);o({provider:n,model:e(n)[0]?.id??``,mode:r?.mode??`byok`})},[o,b]),w=t.useCallback(e=>{o({...a,model:e})},[o,a]);return y?i(`div`,{className:n(`flex items-center gap-2`,c),children:[i(u,{value:a.provider,onValueChange:C,children:[r(p,{className:`w-[140px]`,children:r(m,{})}),r(d,{children:b.map(e=>r(f,{value:e.provider,disabled:!e.available,children:i(`div`,{className:`flex items-center gap-2`,children:[g[e.provider],r(`span`,{children:_[e.provider]})]})},e.provider))})]}),i(u,{value:a.model,onValueChange:w,children:[r(p,{className:`w-[160px]`,children:r(m,{})}),r(d,{children:x.map(e=>r(f,{value:e.id,children:e.name},e.id))})]})]}):i(`div`,{className:n(`flex flex-col gap-3`,c),children:[i(`div`,{className:`flex flex-col gap-1.5`,children:[r(`label`,{className:`text-sm font-medium`,children:`Provider`}),r(`div`,{className:`flex flex-wrap gap-2`,children:b.map(e=>i(l,{variant:a.provider===e.provider?`default`:`outline`,size:`sm`,onPress:()=>e.available&&C(e.provider),disabled:!e.available,className:n(!e.available&&`opacity-50`),children:[g[e.provider],r(`span`,{children:_[e.provider]}),r(h,{variant:v[e.mode].variant,className:`ml-1`,children:v[e.mode].label})]},e.provider))})]}),i(`div`,{className:`flex flex-col gap-1.5`,children:[r(`label`,{className:`text-sm font-medium`,children:`Model`}),i(u,{value:a.model,onValueChange:w,children:[r(p,{children:r(m,{placeholder:`Select a model`})}),r(d,{children:x.map(e=>r(f,{value:e.id,children:i(`div`,{className:`flex items-center gap-2`,children:[r(`span`,{children:e.name}),i(`span`,{className:`text-muted-foreground text-xs`,children:[Math.round(e.contextWindow/1e3),`K`]}),e.capabilities.vision&&r(h,{variant:`outline`,className:`text-xs`,children:`Vision`}),e.capabilities.reasoning&&r(h,{variant:`outline`,className:`text-xs`,children:`Reasoning`})]})},e.id))})]})]}),S&&i(`div`,{className:`text-muted-foreground flex flex-wrap gap-2 text-xs`,children:[i(`span`,{children:[`Context: `,Math.round(S.contextWindow/1e3),`K tokens`]}),S.capabilities.vision&&r(`span`,{children:`• Vision`}),S.capabilities.tools&&r(`span`,{children:`• Tools`}),S.capabilities.reasoning&&r(`span`,{children:`• Reasoning`})]})]})}export{y as ModelPicker};
|
|
@@ -1,8 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { CodePreview } from "./CodePreview.js";
|
|
3
|
-
import { ChatMessage } from "./ChatMessage.js";
|
|
4
|
-
import { ChatInput } from "./ChatInput.js";
|
|
5
|
-
import { ModelPicker } from "./ModelPicker.js";
|
|
6
|
-
import { ContextIndicator } from "./ContextIndicator.js";
|
|
7
|
-
|
|
8
|
-
export { ChatContainer, ChatInput, ChatMessage, CodePreview, ContextIndicator, ModelPicker };
|
|
1
|
+
import{ChatContainer as e}from"./ChatContainer.js";import{CodePreview as t}from"./CodePreview.js";import{ChatMessage as n}from"./ChatMessage.js";import{ChatInput as r}from"./ChatInput.js";import{ModelPicker as i}from"./ModelPicker.js";import{ContextIndicator as a}from"./ContextIndicator.js";export{e as ChatContainer,r as ChatInput,n as ChatMessage,t as CodePreview,a as ContextIndicator,i as ModelPicker};
|