@gmickel/gno 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +90 -50
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/assets/screenshots/webui-ask-answer.png +0 -0
- package/assets/screenshots/webui-collections.png +0 -0
- package/assets/screenshots/webui-editor.png +0 -0
- package/assets/screenshots/webui-home.png +0 -0
- package/assets/skill/SKILL.md +12 -12
- package/assets/skill/cli-reference.md +59 -57
- package/assets/skill/examples.md +8 -7
- package/assets/skill/mcp-reference.md +8 -4
- package/package.json +31 -24
- package/src/app/constants.ts +43 -42
- package/src/cli/colors.ts +1 -1
- package/src/cli/commands/ask.ts +44 -43
- package/src/cli/commands/cleanup.ts +9 -8
- package/src/cli/commands/collection/add.ts +12 -12
- package/src/cli/commands/collection/index.ts +4 -4
- package/src/cli/commands/collection/list.ts +26 -25
- package/src/cli/commands/collection/remove.ts +10 -10
- package/src/cli/commands/collection/rename.ts +10 -10
- package/src/cli/commands/context/add.ts +1 -1
- package/src/cli/commands/context/check.ts +17 -17
- package/src/cli/commands/context/index.ts +4 -4
- package/src/cli/commands/context/list.ts +11 -11
- package/src/cli/commands/context/rm.ts +1 -1
- package/src/cli/commands/doctor.ts +86 -84
- package/src/cli/commands/embed.ts +30 -28
- package/src/cli/commands/get.ts +27 -26
- package/src/cli/commands/index-cmd.ts +9 -9
- package/src/cli/commands/index.ts +16 -16
- package/src/cli/commands/init.ts +13 -12
- package/src/cli/commands/ls.ts +20 -19
- package/src/cli/commands/mcp/config.ts +30 -28
- package/src/cli/commands/mcp/index.ts +4 -4
- package/src/cli/commands/mcp/install.ts +17 -17
- package/src/cli/commands/mcp/paths.ts +133 -133
- package/src/cli/commands/mcp/status.ts +21 -21
- package/src/cli/commands/mcp/uninstall.ts +13 -13
- package/src/cli/commands/mcp.ts +2 -2
- package/src/cli/commands/models/clear.ts +12 -11
- package/src/cli/commands/models/index.ts +5 -5
- package/src/cli/commands/models/list.ts +31 -30
- package/src/cli/commands/models/path.ts +1 -1
- package/src/cli/commands/models/pull.ts +19 -18
- package/src/cli/commands/models/use.ts +4 -4
- package/src/cli/commands/multi-get.ts +38 -36
- package/src/cli/commands/query.ts +21 -20
- package/src/cli/commands/ref-parser.ts +10 -10
- package/src/cli/commands/reset.ts +40 -39
- package/src/cli/commands/search.ts +14 -13
- package/src/cli/commands/serve.ts +4 -4
- package/src/cli/commands/shared.ts +11 -10
- package/src/cli/commands/skill/index.ts +5 -5
- package/src/cli/commands/skill/install.ts +18 -17
- package/src/cli/commands/skill/paths-cmd.ts +11 -10
- package/src/cli/commands/skill/paths.ts +23 -23
- package/src/cli/commands/skill/show.ts +13 -12
- package/src/cli/commands/skill/uninstall.ts +16 -15
- package/src/cli/commands/status.ts +25 -24
- package/src/cli/commands/update.ts +3 -3
- package/src/cli/commands/vsearch.ts +17 -16
- package/src/cli/context.ts +5 -5
- package/src/cli/errors.ts +3 -3
- package/src/cli/format/search-results.ts +37 -37
- package/src/cli/options.ts +43 -43
- package/src/cli/program.ts +455 -459
- package/src/cli/progress.ts +1 -1
- package/src/cli/run.ts +24 -23
- package/src/collection/add.ts +9 -8
- package/src/collection/index.ts +3 -3
- package/src/collection/remove.ts +7 -6
- package/src/collection/types.ts +6 -6
- package/src/config/defaults.ts +1 -1
- package/src/config/index.ts +5 -5
- package/src/config/loader.ts +19 -18
- package/src/config/paths.ts +9 -8
- package/src/config/saver.ts +14 -13
- package/src/config/types.ts +53 -52
- package/src/converters/adapters/markitdownTs/adapter.ts +21 -19
- package/src/converters/adapters/officeparser/adapter.ts +18 -16
- package/src/converters/canonicalize.ts +12 -12
- package/src/converters/errors.ts +26 -22
- package/src/converters/index.ts +8 -8
- package/src/converters/mime.ts +25 -25
- package/src/converters/native/markdown.ts +10 -9
- package/src/converters/native/plaintext.ts +8 -7
- package/src/converters/path.ts +2 -2
- package/src/converters/pipeline.ts +11 -10
- package/src/converters/registry.ts +8 -8
- package/src/converters/types.ts +14 -14
- package/src/converters/versions.ts +4 -4
- package/src/index.ts +4 -4
- package/src/ingestion/chunker.ts +10 -9
- package/src/ingestion/index.ts +6 -6
- package/src/ingestion/language.ts +62 -62
- package/src/ingestion/sync.ts +50 -49
- package/src/ingestion/types.ts +10 -10
- package/src/ingestion/walker.ts +14 -13
- package/src/llm/cache.ts +51 -49
- package/src/llm/errors.ts +40 -36
- package/src/llm/index.ts +9 -9
- package/src/llm/lockfile.ts +6 -6
- package/src/llm/nodeLlamaCpp/adapter.ts +13 -12
- package/src/llm/nodeLlamaCpp/embedding.ts +9 -8
- package/src/llm/nodeLlamaCpp/generation.ts +7 -6
- package/src/llm/nodeLlamaCpp/lifecycle.ts +11 -10
- package/src/llm/nodeLlamaCpp/rerank.ts +6 -5
- package/src/llm/policy.ts +5 -5
- package/src/llm/registry.ts +6 -5
- package/src/llm/types.ts +2 -2
- package/src/mcp/resources/index.ts +15 -13
- package/src/mcp/server.ts +25 -23
- package/src/mcp/tools/get.ts +25 -23
- package/src/mcp/tools/index.ts +32 -29
- package/src/mcp/tools/multi-get.ts +34 -32
- package/src/mcp/tools/query.ts +29 -27
- package/src/mcp/tools/search.ts +14 -12
- package/src/mcp/tools/status.ts +12 -11
- package/src/mcp/tools/vsearch.ts +26 -24
- package/src/pipeline/answer.ts +9 -9
- package/src/pipeline/chunk-lookup.ts +1 -1
- package/src/pipeline/contextual.ts +4 -4
- package/src/pipeline/expansion.ts +23 -21
- package/src/pipeline/explain.ts +21 -21
- package/src/pipeline/fusion.ts +9 -9
- package/src/pipeline/hybrid.ts +41 -42
- package/src/pipeline/index.ts +10 -10
- package/src/pipeline/query-language.ts +39 -39
- package/src/pipeline/rerank.ts +8 -7
- package/src/pipeline/search.ts +22 -22
- package/src/pipeline/types.ts +8 -8
- package/src/pipeline/vsearch.ts +21 -24
- package/src/serve/CLAUDE.md +21 -15
- package/src/serve/config-sync.ts +9 -8
- package/src/serve/context.ts +19 -18
- package/src/serve/index.ts +1 -1
- package/src/serve/jobs.ts +7 -7
- package/src/serve/public/app.tsx +79 -25
- package/src/serve/public/components/AddCollectionDialog.tsx +382 -0
- package/src/serve/public/components/CaptureButton.tsx +60 -0
- package/src/serve/public/components/CaptureModal.tsx +365 -0
- package/src/serve/public/components/IndexingProgress.tsx +333 -0
- package/src/serve/public/components/ShortcutHelpModal.tsx +106 -0
- package/src/serve/public/components/ai-elements/code-block.tsx +42 -32
- package/src/serve/public/components/ai-elements/conversation.tsx +16 -14
- package/src/serve/public/components/ai-elements/inline-citation.tsx +33 -32
- package/src/serve/public/components/ai-elements/loader.tsx +5 -4
- package/src/serve/public/components/ai-elements/message.tsx +39 -37
- package/src/serve/public/components/ai-elements/prompt-input.tsx +97 -95
- package/src/serve/public/components/ai-elements/sources.tsx +12 -10
- package/src/serve/public/components/ai-elements/suggestion.tsx +10 -9
- package/src/serve/public/components/editor/CodeMirrorEditor.tsx +142 -0
- package/src/serve/public/components/editor/MarkdownPreview.tsx +311 -0
- package/src/serve/public/components/editor/index.ts +6 -0
- package/src/serve/public/components/preset-selector.tsx +29 -28
- package/src/serve/public/components/ui/badge.tsx +13 -12
- package/src/serve/public/components/ui/button-group.tsx +13 -12
- package/src/serve/public/components/ui/button.tsx +23 -22
- package/src/serve/public/components/ui/card.tsx +16 -16
- package/src/serve/public/components/ui/carousel.tsx +36 -35
- package/src/serve/public/components/ui/collapsible.tsx +1 -1
- package/src/serve/public/components/ui/command.tsx +17 -15
- package/src/serve/public/components/ui/dialog.tsx +13 -12
- package/src/serve/public/components/ui/dropdown-menu.tsx +13 -12
- package/src/serve/public/components/ui/hover-card.tsx +6 -5
- package/src/serve/public/components/ui/input-group.tsx +45 -43
- package/src/serve/public/components/ui/input.tsx +6 -6
- package/src/serve/public/components/ui/progress.tsx +5 -4
- package/src/serve/public/components/ui/scroll-area.tsx +11 -10
- package/src/serve/public/components/ui/select.tsx +19 -18
- package/src/serve/public/components/ui/separator.tsx +6 -5
- package/src/serve/public/components/ui/table.tsx +18 -18
- package/src/serve/public/components/ui/textarea.tsx +4 -4
- package/src/serve/public/components/ui/tooltip.tsx +5 -4
- package/src/serve/public/globals.css +27 -4
- package/src/serve/public/hooks/use-api.ts +8 -8
- package/src/serve/public/hooks/useCaptureModal.tsx +83 -0
- package/src/serve/public/hooks/useKeyboardShortcuts.ts +85 -0
- package/src/serve/public/index.html +4 -4
- package/src/serve/public/lib/utils.ts +6 -0
- package/src/serve/public/pages/Ask.tsx +27 -26
- package/src/serve/public/pages/Browse.tsx +28 -27
- package/src/serve/public/pages/Collections.tsx +439 -0
- package/src/serve/public/pages/Dashboard.tsx +166 -40
- package/src/serve/public/pages/DocView.tsx +258 -73
- package/src/serve/public/pages/DocumentEditor.tsx +510 -0
- package/src/serve/public/pages/Search.tsx +80 -58
- package/src/serve/routes/api.ts +272 -155
- package/src/serve/security.ts +4 -4
- package/src/serve/server.ts +66 -48
- package/src/store/index.ts +5 -5
- package/src/store/migrations/001-initial.ts +24 -23
- package/src/store/migrations/002-documents-fts.ts +7 -6
- package/src/store/migrations/index.ts +4 -4
- package/src/store/migrations/runner.ts +17 -15
- package/src/store/sqlite/adapter.ts +123 -121
- package/src/store/sqlite/fts5-snowball.ts +24 -23
- package/src/store/sqlite/index.ts +1 -1
- package/src/store/sqlite/setup.ts +12 -12
- package/src/store/sqlite/types.ts +4 -4
- package/src/store/types.ts +19 -19
- package/src/store/vector/index.ts +3 -3
- package/src/store/vector/sqlite-vec.ts +23 -20
- package/src/store/vector/stats.ts +10 -8
- package/src/store/vector/types.ts +2 -2
- package/vendor/fts5-snowball/README.md +6 -6
- package/assets/screenshots/webui-ask-answer.jpg +0 -0
- package/assets/screenshots/webui-home.jpg +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShortcutHelpModal - Displays available keyboard shortcuts.
|
|
3
|
+
*
|
|
4
|
+
* Features:
|
|
5
|
+
* - Grouped by context (Global, Editor, Navigation)
|
|
6
|
+
* - Platform-appropriate modifier display
|
|
7
|
+
* - Triggered by Cmd+/ or help button
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { KeyboardIcon } from "lucide-react";
|
|
11
|
+
|
|
12
|
+
import { modKey } from "../hooks/useKeyboardShortcuts";
|
|
13
|
+
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "./ui/dialog";
|
|
14
|
+
|
|
15
|
+
export interface ShortcutHelpModalProps {
|
|
16
|
+
open: boolean;
|
|
17
|
+
onOpenChange: (open: boolean) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ShortcutItem {
|
|
21
|
+
keys: string;
|
|
22
|
+
description: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
interface ShortcutGroup {
|
|
26
|
+
title: string;
|
|
27
|
+
shortcuts: ShortcutItem[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const shortcutGroups: ShortcutGroup[] = [
|
|
31
|
+
{
|
|
32
|
+
title: "Global",
|
|
33
|
+
shortcuts: [
|
|
34
|
+
{ keys: `${modKey}+N`, description: "New note" },
|
|
35
|
+
{ keys: `${modKey}+K`, description: "Focus search" },
|
|
36
|
+
{ keys: `${modKey}+/`, description: "Show shortcuts" },
|
|
37
|
+
{ keys: "Esc", description: "Close modal" },
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
title: "Editor",
|
|
42
|
+
shortcuts: [
|
|
43
|
+
{ keys: `${modKey}+S`, description: "Save" },
|
|
44
|
+
{ keys: `${modKey}+B`, description: "Bold" },
|
|
45
|
+
{ keys: `${modKey}+I`, description: "Italic" },
|
|
46
|
+
{ keys: `${modKey}+K`, description: "Insert link" },
|
|
47
|
+
{ keys: "Esc", description: "Close editor" },
|
|
48
|
+
],
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: "Navigation",
|
|
52
|
+
shortcuts: [{ keys: `${modKey}+Enter`, description: "Submit form" }],
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
export function ShortcutHelpModal({
|
|
57
|
+
open,
|
|
58
|
+
onOpenChange,
|
|
59
|
+
}: ShortcutHelpModalProps) {
|
|
60
|
+
return (
|
|
61
|
+
<Dialog onOpenChange={onOpenChange} open={open}>
|
|
62
|
+
<DialogContent className="max-w-md">
|
|
63
|
+
<DialogHeader>
|
|
64
|
+
<DialogTitle className="flex items-center gap-2">
|
|
65
|
+
<KeyboardIcon className="size-5" />
|
|
66
|
+
Keyboard Shortcuts
|
|
67
|
+
</DialogTitle>
|
|
68
|
+
</DialogHeader>
|
|
69
|
+
|
|
70
|
+
<div className="space-y-6">
|
|
71
|
+
{shortcutGroups.map((group) => (
|
|
72
|
+
<div key={group.title}>
|
|
73
|
+
<h3 className="mb-3 font-medium text-muted-foreground text-xs uppercase tracking-wider">
|
|
74
|
+
{group.title}
|
|
75
|
+
</h3>
|
|
76
|
+
<div className="space-y-2.5">
|
|
77
|
+
{group.shortcuts.map((shortcut) => (
|
|
78
|
+
<div
|
|
79
|
+
className="flex items-center justify-between rounded-md px-2 py-1.5 transition-colors hover:bg-muted/50"
|
|
80
|
+
key={shortcut.keys}
|
|
81
|
+
>
|
|
82
|
+
<span className="text-sm">{shortcut.description}</span>
|
|
83
|
+
<div className="flex items-center gap-1">
|
|
84
|
+
{shortcut.keys.split("+").map((key, i) => (
|
|
85
|
+
<span key={key}>
|
|
86
|
+
{i > 0 && (
|
|
87
|
+
<span className="mx-0.5 text-muted-foreground/50">
|
|
88
|
+
+
|
|
89
|
+
</span>
|
|
90
|
+
)}
|
|
91
|
+
<kbd className="inline-flex min-w-[1.75rem] items-center justify-center rounded border border-border/80 bg-gradient-to-b from-muted/80 to-muted px-1.5 py-0.5 font-mono text-[11px] text-foreground shadow-[0_2px_0_hsl(var(--border)),inset_0_1px_0_hsl(var(--background)/0.5)]">
|
|
92
|
+
{key}
|
|
93
|
+
</kbd>
|
|
94
|
+
</span>
|
|
95
|
+
))}
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
))}
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
))}
|
|
102
|
+
</div>
|
|
103
|
+
</DialogContent>
|
|
104
|
+
</Dialog>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CheckIcon, CopyIcon } from
|
|
1
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
2
2
|
import {
|
|
3
3
|
type ComponentProps,
|
|
4
4
|
createContext,
|
|
@@ -7,10 +7,11 @@ import {
|
|
|
7
7
|
useEffect,
|
|
8
8
|
useRef,
|
|
9
9
|
useState,
|
|
10
|
-
} from
|
|
11
|
-
import { type BundledLanguage, codeToHtml, type ShikiTransformer } from
|
|
12
|
-
|
|
13
|
-
import {
|
|
10
|
+
} from "react";
|
|
11
|
+
import { type BundledLanguage, codeToHtml, type ShikiTransformer } from "shiki";
|
|
12
|
+
|
|
13
|
+
import { cn } from "../../lib/utils";
|
|
14
|
+
import { Button } from "../ui/button";
|
|
14
15
|
|
|
15
16
|
type CodeBlockProps = HTMLAttributes<HTMLDivElement> & {
|
|
16
17
|
code: string;
|
|
@@ -23,26 +24,26 @@ interface CodeBlockContextType {
|
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
const CodeBlockContext = createContext<CodeBlockContextType>({
|
|
26
|
-
code:
|
|
27
|
+
code: "",
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
const lineNumberTransformer: ShikiTransformer = {
|
|
30
|
-
name:
|
|
31
|
+
name: "line-numbers",
|
|
31
32
|
line(node, line) {
|
|
32
33
|
node.children.unshift({
|
|
33
|
-
type:
|
|
34
|
-
tagName:
|
|
34
|
+
type: "element",
|
|
35
|
+
tagName: "span",
|
|
35
36
|
properties: {
|
|
36
37
|
className: [
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
"inline-block",
|
|
39
|
+
"min-w-10",
|
|
40
|
+
"mr-4",
|
|
41
|
+
"text-right",
|
|
42
|
+
"select-none",
|
|
43
|
+
"text-muted-foreground",
|
|
43
44
|
],
|
|
44
45
|
},
|
|
45
|
-
children: [{ type:
|
|
46
|
+
children: [{ type: "text", value: String(line) }],
|
|
46
47
|
});
|
|
47
48
|
},
|
|
48
49
|
};
|
|
@@ -59,12 +60,12 @@ export async function highlightCode(
|
|
|
59
60
|
return await Promise.all([
|
|
60
61
|
codeToHtml(code, {
|
|
61
62
|
lang: language,
|
|
62
|
-
theme:
|
|
63
|
+
theme: "one-light",
|
|
63
64
|
transformers,
|
|
64
65
|
}),
|
|
65
66
|
codeToHtml(code, {
|
|
66
67
|
lang: language,
|
|
67
|
-
theme:
|
|
68
|
+
theme: "one-dark-pro",
|
|
68
69
|
transformers,
|
|
69
70
|
}),
|
|
70
71
|
]);
|
|
@@ -78,21 +79,30 @@ export const CodeBlock = ({
|
|
|
78
79
|
children,
|
|
79
80
|
...props
|
|
80
81
|
}: CodeBlockProps) => {
|
|
81
|
-
const [html, setHtml] = useState<string>(
|
|
82
|
-
const [darkHtml, setDarkHtml] = useState<string>(
|
|
83
|
-
const
|
|
82
|
+
const [html, setHtml] = useState<string>("");
|
|
83
|
+
const [darkHtml, setDarkHtml] = useState<string>("");
|
|
84
|
+
const requestIdRef = useRef(0);
|
|
84
85
|
|
|
85
86
|
useEffect(() => {
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
let cancelled = false;
|
|
88
|
+
const requestId = ++requestIdRef.current;
|
|
89
|
+
|
|
90
|
+
async function highlight() {
|
|
91
|
+
const [light, dark] = await highlightCode(
|
|
92
|
+
code,
|
|
93
|
+
language,
|
|
94
|
+
showLineNumbers
|
|
95
|
+
);
|
|
96
|
+
// Only apply if this is still the latest request AND not cancelled
|
|
97
|
+
if (!cancelled && requestId === requestIdRef.current) {
|
|
88
98
|
setHtml(light);
|
|
89
99
|
setDarkHtml(dark);
|
|
90
|
-
mounted.current = true;
|
|
91
100
|
}
|
|
92
|
-
}
|
|
101
|
+
}
|
|
93
102
|
|
|
103
|
+
void highlight();
|
|
94
104
|
return () => {
|
|
95
|
-
|
|
105
|
+
cancelled = true;
|
|
96
106
|
};
|
|
97
107
|
}, [code, language, showLineNumbers]);
|
|
98
108
|
|
|
@@ -100,7 +110,7 @@ export const CodeBlock = ({
|
|
|
100
110
|
<CodeBlockContext.Provider value={{ code }}>
|
|
101
111
|
<div
|
|
102
112
|
className={cn(
|
|
103
|
-
|
|
113
|
+
"group relative w-full overflow-hidden rounded-md border bg-background text-foreground",
|
|
104
114
|
className
|
|
105
115
|
)}
|
|
106
116
|
{...props}
|
|
@@ -108,12 +118,12 @@ export const CodeBlock = ({
|
|
|
108
118
|
<div className="relative">
|
|
109
119
|
<div
|
|
110
120
|
className="overflow-auto dark:hidden [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm"
|
|
111
|
-
//
|
|
121
|
+
// oxlint-disable-next-line react/no-danger -- syntax highlighting requires innerHTML
|
|
112
122
|
dangerouslySetInnerHTML={{ __html: html }}
|
|
113
123
|
/>
|
|
114
124
|
<div
|
|
115
125
|
className="hidden overflow-auto dark:block [&>pre]:m-0 [&>pre]:bg-background! [&>pre]:p-4 [&>pre]:text-foreground! [&>pre]:text-sm [&_code]:font-mono [&_code]:text-sm"
|
|
116
|
-
//
|
|
126
|
+
// oxlint-disable-next-line react/no-danger -- syntax highlighting requires innerHTML
|
|
117
127
|
dangerouslySetInnerHTML={{ __html: darkHtml }}
|
|
118
128
|
/>
|
|
119
129
|
{children && (
|
|
@@ -145,8 +155,8 @@ export const CodeBlockCopyButton = ({
|
|
|
145
155
|
const { code } = useContext(CodeBlockContext);
|
|
146
156
|
|
|
147
157
|
const copyToClipboard = async () => {
|
|
148
|
-
if (typeof window ===
|
|
149
|
-
onError?.(new Error(
|
|
158
|
+
if (typeof window === "undefined" || !navigator?.clipboard?.writeText) {
|
|
159
|
+
onError?.(new Error("Clipboard API not available"));
|
|
150
160
|
return;
|
|
151
161
|
}
|
|
152
162
|
|
|
@@ -164,7 +174,7 @@ export const CodeBlockCopyButton = ({
|
|
|
164
174
|
|
|
165
175
|
return (
|
|
166
176
|
<Button
|
|
167
|
-
className={cn(
|
|
177
|
+
className={cn("shrink-0", className)}
|
|
168
178
|
onClick={copyToClipboard}
|
|
169
179
|
size="icon"
|
|
170
180
|
variant="ghost"
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
import type { ComponentProps } from "react";
|
|
2
|
+
|
|
3
|
+
import { ArrowDownIcon } from "lucide-react";
|
|
4
|
+
import { useCallback } from "react";
|
|
5
|
+
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../lib/utils";
|
|
8
|
+
import { Button } from "../ui/button";
|
|
7
9
|
|
|
8
10
|
export type ConversationProps = ComponentProps<typeof StickToBottom>;
|
|
9
11
|
|
|
10
12
|
export const Conversation = ({ className, ...props }: ConversationProps) => (
|
|
11
13
|
<StickToBottom
|
|
12
|
-
className={cn(
|
|
14
|
+
className={cn("relative flex-1 overflow-y-hidden", className)}
|
|
13
15
|
initial="smooth"
|
|
14
16
|
resize="smooth"
|
|
15
17
|
role="log"
|
|
@@ -26,12 +28,12 @@ export const ConversationContent = ({
|
|
|
26
28
|
...props
|
|
27
29
|
}: ConversationContentProps) => (
|
|
28
30
|
<StickToBottom.Content
|
|
29
|
-
className={cn(
|
|
31
|
+
className={cn("flex flex-col gap-8 p-4", className)}
|
|
30
32
|
{...props}
|
|
31
33
|
/>
|
|
32
34
|
);
|
|
33
35
|
|
|
34
|
-
export type ConversationEmptyStateProps = ComponentProps<
|
|
36
|
+
export type ConversationEmptyStateProps = ComponentProps<"div"> & {
|
|
35
37
|
title?: string;
|
|
36
38
|
description?: string;
|
|
37
39
|
icon?: React.ReactNode;
|
|
@@ -39,15 +41,15 @@ export type ConversationEmptyStateProps = ComponentProps<'div'> & {
|
|
|
39
41
|
|
|
40
42
|
export const ConversationEmptyState = ({
|
|
41
43
|
className,
|
|
42
|
-
title =
|
|
43
|
-
description =
|
|
44
|
+
title = "No messages yet",
|
|
45
|
+
description = "Start a conversation to see messages here",
|
|
44
46
|
icon,
|
|
45
47
|
children,
|
|
46
48
|
...props
|
|
47
49
|
}: ConversationEmptyStateProps) => (
|
|
48
50
|
<div
|
|
49
51
|
className={cn(
|
|
50
|
-
|
|
52
|
+
"flex size-full flex-col items-center justify-center gap-3 p-8 text-center",
|
|
51
53
|
className
|
|
52
54
|
)}
|
|
53
55
|
{...props}
|
|
@@ -75,14 +77,14 @@ export const ConversationScrollButton = ({
|
|
|
75
77
|
const { isAtBottom, scrollToBottom } = useStickToBottomContext();
|
|
76
78
|
|
|
77
79
|
const handleScrollToBottom = useCallback(() => {
|
|
78
|
-
scrollToBottom();
|
|
80
|
+
void scrollToBottom();
|
|
79
81
|
}, [scrollToBottom]);
|
|
80
82
|
|
|
81
83
|
return (
|
|
82
84
|
!isAtBottom && (
|
|
83
85
|
<Button
|
|
84
86
|
className={cn(
|
|
85
|
-
|
|
87
|
+
"absolute bottom-4 left-[50%] translate-x-[-50%] rounded-full",
|
|
86
88
|
className
|
|
87
89
|
)}
|
|
88
90
|
onClick={handleScrollToBottom}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrowLeftIcon, ArrowRightIcon } from
|
|
1
|
+
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react";
|
|
2
2
|
import {
|
|
3
3
|
type ComponentProps,
|
|
4
4
|
createContext,
|
|
@@ -6,41 +6,42 @@ import {
|
|
|
6
6
|
useContext,
|
|
7
7
|
useEffect,
|
|
8
8
|
useState,
|
|
9
|
-
} from
|
|
10
|
-
|
|
11
|
-
import {
|
|
9
|
+
} from "react";
|
|
10
|
+
|
|
11
|
+
import { cn } from "../../lib/utils";
|
|
12
|
+
import { Badge } from "../ui/badge";
|
|
12
13
|
import {
|
|
13
14
|
Carousel,
|
|
14
15
|
type CarouselApi,
|
|
15
16
|
CarouselContent,
|
|
16
17
|
CarouselItem,
|
|
17
|
-
} from
|
|
18
|
+
} from "../ui/carousel";
|
|
18
19
|
import {
|
|
19
20
|
HoverCard,
|
|
20
21
|
HoverCardContent,
|
|
21
22
|
HoverCardTrigger,
|
|
22
|
-
} from
|
|
23
|
+
} from "../ui/hover-card";
|
|
23
24
|
|
|
24
|
-
export type InlineCitationProps = ComponentProps<
|
|
25
|
+
export type InlineCitationProps = ComponentProps<"span">;
|
|
25
26
|
|
|
26
27
|
export const InlineCitation = ({
|
|
27
28
|
className,
|
|
28
29
|
...props
|
|
29
30
|
}: InlineCitationProps) => (
|
|
30
31
|
<span
|
|
31
|
-
className={cn(
|
|
32
|
+
className={cn("group inline items-center gap-1", className)}
|
|
32
33
|
{...props}
|
|
33
34
|
/>
|
|
34
35
|
);
|
|
35
36
|
|
|
36
|
-
export type InlineCitationTextProps = ComponentProps<
|
|
37
|
+
export type InlineCitationTextProps = ComponentProps<"span">;
|
|
37
38
|
|
|
38
39
|
export const InlineCitationText = ({
|
|
39
40
|
className,
|
|
40
41
|
...props
|
|
41
42
|
}: InlineCitationTextProps) => (
|
|
42
43
|
<span
|
|
43
|
-
className={cn(
|
|
44
|
+
className={cn("transition-colors group-hover:bg-accent", className)}
|
|
44
45
|
{...props}
|
|
45
46
|
/>
|
|
46
47
|
);
|
|
@@ -62,29 +63,29 @@ export const InlineCitationCardTrigger = ({
|
|
|
62
63
|
}: InlineCitationCardTriggerProps) => (
|
|
63
64
|
<HoverCardTrigger asChild>
|
|
64
65
|
<Badge
|
|
65
|
-
className={cn(
|
|
66
|
+
className={cn("ml-1 rounded-full", className)}
|
|
66
67
|
variant="secondary"
|
|
67
68
|
{...props}
|
|
68
69
|
>
|
|
69
70
|
{sources[0] ? (
|
|
70
71
|
<>
|
|
71
|
-
{new URL(sources[0]).hostname}{
|
|
72
|
+
{new URL(sources[0]).hostname}{" "}
|
|
72
73
|
{sources.length > 1 && `+${sources.length - 1}`}
|
|
73
74
|
</>
|
|
74
75
|
) : (
|
|
75
|
-
|
|
76
|
+
"unknown"
|
|
76
77
|
)}
|
|
77
78
|
</Badge>
|
|
78
79
|
</HoverCardTrigger>
|
|
79
80
|
);
|
|
80
81
|
|
|
81
|
-
export type InlineCitationCardBodyProps = ComponentProps<
|
|
82
|
+
export type InlineCitationCardBodyProps = ComponentProps<"div">;
|
|
82
83
|
|
|
83
84
|
export const InlineCitationCardBody = ({
|
|
84
85
|
className,
|
|
85
86
|
...props
|
|
86
87
|
}: InlineCitationCardBodyProps) => (
|
|
87
|
-
<HoverCardContent className={cn(
|
|
88
|
+
<HoverCardContent className={cn("relative w-80 p-0", className)} {...props} />
|
|
88
89
|
);
|
|
89
90
|
|
|
90
91
|
const CarouselApiContext = createContext<CarouselApi | undefined>(undefined);
|
|
@@ -105,32 +106,32 @@ export const InlineCitationCarousel = ({
|
|
|
105
106
|
|
|
106
107
|
return (
|
|
107
108
|
<CarouselApiContext.Provider value={api}>
|
|
108
|
-
<Carousel className={cn(
|
|
109
|
+
<Carousel className={cn("w-full", className)} setApi={setApi} {...props}>
|
|
109
110
|
{children}
|
|
110
111
|
</Carousel>
|
|
111
112
|
</CarouselApiContext.Provider>
|
|
112
113
|
);
|
|
113
114
|
};
|
|
114
115
|
|
|
115
|
-
export type InlineCitationCarouselContentProps = ComponentProps<
|
|
116
|
+
export type InlineCitationCarouselContentProps = ComponentProps<"div">;
|
|
116
117
|
|
|
117
118
|
export const InlineCitationCarouselContent = (
|
|
118
119
|
props: InlineCitationCarouselContentProps
|
|
119
120
|
) => <CarouselContent {...props} />;
|
|
120
121
|
|
|
121
|
-
export type InlineCitationCarouselItemProps = ComponentProps<
|
|
122
|
+
export type InlineCitationCarouselItemProps = ComponentProps<"div">;
|
|
122
123
|
|
|
123
124
|
export const InlineCitationCarouselItem = ({
|
|
124
125
|
className,
|
|
125
126
|
...props
|
|
126
127
|
}: InlineCitationCarouselItemProps) => (
|
|
127
128
|
<CarouselItem
|
|
128
|
-
className={cn(
|
|
129
|
+
className={cn("w-full space-y-2 p-4 pl-8", className)}
|
|
129
130
|
{...props}
|
|
130
131
|
/>
|
|
131
132
|
);
|
|
132
133
|
|
|
133
|
-
export type InlineCitationCarouselHeaderProps = ComponentProps<
|
|
134
|
+
export type InlineCitationCarouselHeaderProps = ComponentProps<"div">;
|
|
134
135
|
|
|
135
136
|
export const InlineCitationCarouselHeader = ({
|
|
136
137
|
className,
|
|
@@ -138,14 +139,14 @@ export const InlineCitationCarouselHeader = ({
|
|
|
138
139
|
}: InlineCitationCarouselHeaderProps) => (
|
|
139
140
|
<div
|
|
140
141
|
className={cn(
|
|
141
|
-
|
|
142
|
+
"flex items-center justify-between gap-2 rounded-t-md bg-secondary p-2",
|
|
142
143
|
className
|
|
143
144
|
)}
|
|
144
145
|
{...props}
|
|
145
146
|
/>
|
|
146
147
|
);
|
|
147
148
|
|
|
148
|
-
export type InlineCitationCarouselIndexProps = ComponentProps<
|
|
149
|
+
export type InlineCitationCarouselIndexProps = ComponentProps<"div">;
|
|
149
150
|
|
|
150
151
|
export const InlineCitationCarouselIndex = ({
|
|
151
152
|
children,
|
|
@@ -164,7 +165,7 @@ export const InlineCitationCarouselIndex = ({
|
|
|
164
165
|
setCount(api.scrollSnapList().length);
|
|
165
166
|
setCurrent(api.selectedScrollSnap() + 1);
|
|
166
167
|
|
|
167
|
-
api.on(
|
|
168
|
+
api.on("select", () => {
|
|
168
169
|
setCurrent(api.selectedScrollSnap() + 1);
|
|
169
170
|
});
|
|
170
171
|
}, [api]);
|
|
@@ -172,7 +173,7 @@ export const InlineCitationCarouselIndex = ({
|
|
|
172
173
|
return (
|
|
173
174
|
<div
|
|
174
175
|
className={cn(
|
|
175
|
-
|
|
176
|
+
"flex flex-1 items-center justify-end px-3 py-1 text-muted-foreground text-xs",
|
|
176
177
|
className
|
|
177
178
|
)}
|
|
178
179
|
{...props}
|
|
@@ -182,7 +183,7 @@ export const InlineCitationCarouselIndex = ({
|
|
|
182
183
|
);
|
|
183
184
|
};
|
|
184
185
|
|
|
185
|
-
export type InlineCitationCarouselPrevProps = ComponentProps<
|
|
186
|
+
export type InlineCitationCarouselPrevProps = ComponentProps<"button">;
|
|
186
187
|
|
|
187
188
|
export const InlineCitationCarouselPrev = ({
|
|
188
189
|
className,
|
|
@@ -199,7 +200,7 @@ export const InlineCitationCarouselPrev = ({
|
|
|
199
200
|
return (
|
|
200
201
|
<button
|
|
201
202
|
aria-label="Previous"
|
|
202
|
-
className={cn(
|
|
203
|
+
className={cn("shrink-0", className)}
|
|
203
204
|
onClick={handleClick}
|
|
204
205
|
type="button"
|
|
205
206
|
{...props}
|
|
@@ -209,7 +210,7 @@ export const InlineCitationCarouselPrev = ({
|
|
|
209
210
|
);
|
|
210
211
|
};
|
|
211
212
|
|
|
212
|
-
export type InlineCitationCarouselNextProps = ComponentProps<
|
|
213
|
+
export type InlineCitationCarouselNextProps = ComponentProps<"button">;
|
|
213
214
|
|
|
214
215
|
export const InlineCitationCarouselNext = ({
|
|
215
216
|
className,
|
|
@@ -226,7 +227,7 @@ export const InlineCitationCarouselNext = ({
|
|
|
226
227
|
return (
|
|
227
228
|
<button
|
|
228
229
|
aria-label="Next"
|
|
229
|
-
className={cn(
|
|
230
|
+
className={cn("shrink-0", className)}
|
|
230
231
|
onClick={handleClick}
|
|
231
232
|
type="button"
|
|
232
233
|
{...props}
|
|
@@ -236,7 +237,7 @@ export const InlineCitationCarouselNext = ({
|
|
|
236
237
|
);
|
|
237
238
|
};
|
|
238
239
|
|
|
239
|
-
export type InlineCitationSourceProps = ComponentProps<
|
|
240
|
+
export type InlineCitationSourceProps = ComponentProps<"div"> & {
|
|
240
241
|
title?: string;
|
|
241
242
|
url?: string;
|
|
242
243
|
description?: string;
|
|
@@ -250,7 +251,7 @@ export const InlineCitationSource = ({
|
|
|
250
251
|
children,
|
|
251
252
|
...props
|
|
252
253
|
}: InlineCitationSourceProps) => (
|
|
253
|
-
<div className={cn(
|
|
254
|
+
<div className={cn("space-y-1", className)} {...props}>
|
|
254
255
|
{title && (
|
|
255
256
|
<h4 className="truncate font-medium text-sm leading-tight">{title}</h4>
|
|
256
257
|
)}
|
|
@@ -266,7 +267,7 @@ export const InlineCitationSource = ({
|
|
|
266
267
|
</div>
|
|
267
268
|
);
|
|
268
269
|
|
|
269
|
-
export type InlineCitationQuoteProps = ComponentProps<
|
|
270
|
+
export type InlineCitationQuoteProps = ComponentProps<"blockquote">;
|
|
270
271
|
|
|
271
272
|
export const InlineCitationQuote = ({
|
|
272
273
|
children,
|
|
@@ -275,7 +276,7 @@ export const InlineCitationQuote = ({
|
|
|
275
276
|
}: InlineCitationQuoteProps) => (
|
|
276
277
|
<blockquote
|
|
277
278
|
className={cn(
|
|
278
|
-
|
|
279
|
+
"border-muted border-l-2 pl-3 text-muted-foreground text-sm italic",
|
|
279
280
|
className
|
|
280
281
|
)}
|
|
281
282
|
{...props}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { HTMLAttributes } from
|
|
2
|
-
|
|
1
|
+
import type { HTMLAttributes } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
3
4
|
|
|
4
5
|
interface LoaderIconProps {
|
|
5
6
|
size?: number;
|
|
@@ -9,7 +10,7 @@ const LoaderIcon = ({ size = 16 }: LoaderIconProps) => (
|
|
|
9
10
|
<svg
|
|
10
11
|
height={size}
|
|
11
12
|
strokeLinejoin="round"
|
|
12
|
-
style={{ color:
|
|
13
|
+
style={{ color: "currentcolor" }}
|
|
13
14
|
viewBox="0 0 16 16"
|
|
14
15
|
width={size}
|
|
15
16
|
>
|
|
@@ -86,7 +87,7 @@ export type LoaderProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
86
87
|
export const Loader = ({ className, size = 16, ...props }: LoaderProps) => (
|
|
87
88
|
<div
|
|
88
89
|
className={cn(
|
|
89
|
-
|
|
90
|
+
"inline-flex animate-spin items-center justify-center",
|
|
90
91
|
className
|
|
91
92
|
)}
|
|
92
93
|
{...props}
|