@gmickel/gno 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +194 -53
  2. package/assets/badges/license.svg +12 -0
  3. package/assets/badges/npm.svg +13 -0
  4. package/assets/badges/twitter.svg +22 -0
  5. package/assets/badges/website.svg +22 -0
  6. package/package.json +30 -1
  7. package/src/cli/commands/ask.ts +11 -186
  8. package/src/cli/commands/models/pull.ts +9 -4
  9. package/src/cli/commands/serve.ts +19 -0
  10. package/src/cli/program.ts +28 -0
  11. package/src/llm/registry.ts +3 -1
  12. package/src/pipeline/answer.ts +191 -0
  13. package/src/serve/CLAUDE.md +91 -0
  14. package/src/serve/bunfig.toml +2 -0
  15. package/src/serve/context.ts +181 -0
  16. package/src/serve/index.ts +7 -0
  17. package/src/serve/public/app.tsx +56 -0
  18. package/src/serve/public/components/ai-elements/code-block.tsx +176 -0
  19. package/src/serve/public/components/ai-elements/conversation.tsx +98 -0
  20. package/src/serve/public/components/ai-elements/inline-citation.tsx +285 -0
  21. package/src/serve/public/components/ai-elements/loader.tsx +96 -0
  22. package/src/serve/public/components/ai-elements/message.tsx +443 -0
  23. package/src/serve/public/components/ai-elements/prompt-input.tsx +1421 -0
  24. package/src/serve/public/components/ai-elements/sources.tsx +75 -0
  25. package/src/serve/public/components/ai-elements/suggestion.tsx +51 -0
  26. package/src/serve/public/components/preset-selector.tsx +403 -0
  27. package/src/serve/public/components/ui/badge.tsx +46 -0
  28. package/src/serve/public/components/ui/button-group.tsx +82 -0
  29. package/src/serve/public/components/ui/button.tsx +62 -0
  30. package/src/serve/public/components/ui/card.tsx +92 -0
  31. package/src/serve/public/components/ui/carousel.tsx +244 -0
  32. package/src/serve/public/components/ui/collapsible.tsx +31 -0
  33. package/src/serve/public/components/ui/command.tsx +181 -0
  34. package/src/serve/public/components/ui/dialog.tsx +141 -0
  35. package/src/serve/public/components/ui/dropdown-menu.tsx +255 -0
  36. package/src/serve/public/components/ui/hover-card.tsx +42 -0
  37. package/src/serve/public/components/ui/input-group.tsx +167 -0
  38. package/src/serve/public/components/ui/input.tsx +21 -0
  39. package/src/serve/public/components/ui/progress.tsx +28 -0
  40. package/src/serve/public/components/ui/scroll-area.tsx +56 -0
  41. package/src/serve/public/components/ui/select.tsx +188 -0
  42. package/src/serve/public/components/ui/separator.tsx +26 -0
  43. package/src/serve/public/components/ui/table.tsx +114 -0
  44. package/src/serve/public/components/ui/textarea.tsx +18 -0
  45. package/src/serve/public/components/ui/tooltip.tsx +59 -0
  46. package/src/serve/public/globals.css +226 -0
  47. package/src/serve/public/hooks/use-api.ts +112 -0
  48. package/src/serve/public/index.html +13 -0
  49. package/src/serve/public/pages/Ask.tsx +442 -0
  50. package/src/serve/public/pages/Browse.tsx +270 -0
  51. package/src/serve/public/pages/Dashboard.tsx +202 -0
  52. package/src/serve/public/pages/DocView.tsx +302 -0
  53. package/src/serve/public/pages/Search.tsx +335 -0
  54. package/src/serve/routes/api.ts +763 -0
  55. package/src/serve/server.ts +249 -0
  56. package/src/store/sqlite/adapter.ts +47 -0
  57. package/src/store/types.ts +10 -0
@@ -0,0 +1,285 @@
1
+ import { ArrowLeftIcon, ArrowRightIcon } from 'lucide-react';
2
+ import {
3
+ type ComponentProps,
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useState,
9
+ } from 'react';
10
+ import { cn } from '../../lib/utils';
11
+ import { Badge } from '../ui/badge';
12
+ import {
13
+ Carousel,
14
+ type CarouselApi,
15
+ CarouselContent,
16
+ CarouselItem,
17
+ } from '../ui/carousel';
18
+ import {
19
+ HoverCard,
20
+ HoverCardContent,
21
+ HoverCardTrigger,
22
+ } from '../ui/hover-card';
23
+
24
+ export type InlineCitationProps = ComponentProps<'span'>;
25
+
26
+ export const InlineCitation = ({
27
+ className,
28
+ ...props
29
+ }: InlineCitationProps) => (
30
+ <span
31
+ className={cn('group inline items-center gap-1', className)}
32
+ {...props}
33
+ />
34
+ );
35
+
36
+ export type InlineCitationTextProps = ComponentProps<'span'>;
37
+
38
+ export const InlineCitationText = ({
39
+ className,
40
+ ...props
41
+ }: InlineCitationTextProps) => (
42
+ <span
43
+ className={cn('transition-colors group-hover:bg-accent', className)}
44
+ {...props}
45
+ />
46
+ );
47
+
48
+ export type InlineCitationCardProps = ComponentProps<typeof HoverCard>;
49
+
50
+ export const InlineCitationCard = (props: InlineCitationCardProps) => (
51
+ <HoverCard closeDelay={0} openDelay={0} {...props} />
52
+ );
53
+
54
+ export type InlineCitationCardTriggerProps = ComponentProps<typeof Badge> & {
55
+ sources: string[];
56
+ };
57
+
58
+ export const InlineCitationCardTrigger = ({
59
+ sources,
60
+ className,
61
+ ...props
62
+ }: InlineCitationCardTriggerProps) => (
63
+ <HoverCardTrigger asChild>
64
+ <Badge
65
+ className={cn('ml-1 rounded-full', className)}
66
+ variant="secondary"
67
+ {...props}
68
+ >
69
+ {sources[0] ? (
70
+ <>
71
+ {new URL(sources[0]).hostname}{' '}
72
+ {sources.length > 1 && `+${sources.length - 1}`}
73
+ </>
74
+ ) : (
75
+ 'unknown'
76
+ )}
77
+ </Badge>
78
+ </HoverCardTrigger>
79
+ );
80
+
81
+ export type InlineCitationCardBodyProps = ComponentProps<'div'>;
82
+
83
+ export const InlineCitationCardBody = ({
84
+ className,
85
+ ...props
86
+ }: InlineCitationCardBodyProps) => (
87
+ <HoverCardContent className={cn('relative w-80 p-0', className)} {...props} />
88
+ );
89
+
90
+ const CarouselApiContext = createContext<CarouselApi | undefined>(undefined);
91
+
92
+ const useCarouselApi = () => {
93
+ const context = useContext(CarouselApiContext);
94
+ return context;
95
+ };
96
+
97
+ export type InlineCitationCarouselProps = ComponentProps<typeof Carousel>;
98
+
99
+ export const InlineCitationCarousel = ({
100
+ className,
101
+ children,
102
+ ...props
103
+ }: InlineCitationCarouselProps) => {
104
+ const [api, setApi] = useState<CarouselApi>();
105
+
106
+ return (
107
+ <CarouselApiContext.Provider value={api}>
108
+ <Carousel className={cn('w-full', className)} setApi={setApi} {...props}>
109
+ {children}
110
+ </Carousel>
111
+ </CarouselApiContext.Provider>
112
+ );
113
+ };
114
+
115
+ export type InlineCitationCarouselContentProps = ComponentProps<'div'>;
116
+
117
+ export const InlineCitationCarouselContent = (
118
+ props: InlineCitationCarouselContentProps
119
+ ) => <CarouselContent {...props} />;
120
+
121
+ export type InlineCitationCarouselItemProps = ComponentProps<'div'>;
122
+
123
+ export const InlineCitationCarouselItem = ({
124
+ className,
125
+ ...props
126
+ }: InlineCitationCarouselItemProps) => (
127
+ <CarouselItem
128
+ className={cn('w-full space-y-2 p-4 pl-8', className)}
129
+ {...props}
130
+ />
131
+ );
132
+
133
+ export type InlineCitationCarouselHeaderProps = ComponentProps<'div'>;
134
+
135
+ export const InlineCitationCarouselHeader = ({
136
+ className,
137
+ ...props
138
+ }: InlineCitationCarouselHeaderProps) => (
139
+ <div
140
+ className={cn(
141
+ 'flex items-center justify-between gap-2 rounded-t-md bg-secondary p-2',
142
+ className
143
+ )}
144
+ {...props}
145
+ />
146
+ );
147
+
148
+ export type InlineCitationCarouselIndexProps = ComponentProps<'div'>;
149
+
150
+ export const InlineCitationCarouselIndex = ({
151
+ children,
152
+ className,
153
+ ...props
154
+ }: InlineCitationCarouselIndexProps) => {
155
+ const api = useCarouselApi();
156
+ const [current, setCurrent] = useState(0);
157
+ const [count, setCount] = useState(0);
158
+
159
+ useEffect(() => {
160
+ if (!api) {
161
+ return;
162
+ }
163
+
164
+ setCount(api.scrollSnapList().length);
165
+ setCurrent(api.selectedScrollSnap() + 1);
166
+
167
+ api.on('select', () => {
168
+ setCurrent(api.selectedScrollSnap() + 1);
169
+ });
170
+ }, [api]);
171
+
172
+ return (
173
+ <div
174
+ className={cn(
175
+ 'flex flex-1 items-center justify-end px-3 py-1 text-muted-foreground text-xs',
176
+ className
177
+ )}
178
+ {...props}
179
+ >
180
+ {children ?? `${current}/${count}`}
181
+ </div>
182
+ );
183
+ };
184
+
185
+ export type InlineCitationCarouselPrevProps = ComponentProps<'button'>;
186
+
187
+ export const InlineCitationCarouselPrev = ({
188
+ className,
189
+ ...props
190
+ }: InlineCitationCarouselPrevProps) => {
191
+ const api = useCarouselApi();
192
+
193
+ const handleClick = useCallback(() => {
194
+ if (api) {
195
+ api.scrollPrev();
196
+ }
197
+ }, [api]);
198
+
199
+ return (
200
+ <button
201
+ aria-label="Previous"
202
+ className={cn('shrink-0', className)}
203
+ onClick={handleClick}
204
+ type="button"
205
+ {...props}
206
+ >
207
+ <ArrowLeftIcon className="size-4 text-muted-foreground" />
208
+ </button>
209
+ );
210
+ };
211
+
212
+ export type InlineCitationCarouselNextProps = ComponentProps<'button'>;
213
+
214
+ export const InlineCitationCarouselNext = ({
215
+ className,
216
+ ...props
217
+ }: InlineCitationCarouselNextProps) => {
218
+ const api = useCarouselApi();
219
+
220
+ const handleClick = useCallback(() => {
221
+ if (api) {
222
+ api.scrollNext();
223
+ }
224
+ }, [api]);
225
+
226
+ return (
227
+ <button
228
+ aria-label="Next"
229
+ className={cn('shrink-0', className)}
230
+ onClick={handleClick}
231
+ type="button"
232
+ {...props}
233
+ >
234
+ <ArrowRightIcon className="size-4 text-muted-foreground" />
235
+ </button>
236
+ );
237
+ };
238
+
239
+ export type InlineCitationSourceProps = ComponentProps<'div'> & {
240
+ title?: string;
241
+ url?: string;
242
+ description?: string;
243
+ };
244
+
245
+ export const InlineCitationSource = ({
246
+ title,
247
+ url,
248
+ description,
249
+ className,
250
+ children,
251
+ ...props
252
+ }: InlineCitationSourceProps) => (
253
+ <div className={cn('space-y-1', className)} {...props}>
254
+ {title && (
255
+ <h4 className="truncate font-medium text-sm leading-tight">{title}</h4>
256
+ )}
257
+ {url && (
258
+ <p className="truncate break-all text-muted-foreground text-xs">{url}</p>
259
+ )}
260
+ {description && (
261
+ <p className="line-clamp-3 text-muted-foreground text-sm leading-relaxed">
262
+ {description}
263
+ </p>
264
+ )}
265
+ {children}
266
+ </div>
267
+ );
268
+
269
+ export type InlineCitationQuoteProps = ComponentProps<'blockquote'>;
270
+
271
+ export const InlineCitationQuote = ({
272
+ children,
273
+ className,
274
+ ...props
275
+ }: InlineCitationQuoteProps) => (
276
+ <blockquote
277
+ className={cn(
278
+ 'border-muted border-l-2 pl-3 text-muted-foreground text-sm italic',
279
+ className
280
+ )}
281
+ {...props}
282
+ >
283
+ {children}
284
+ </blockquote>
285
+ );
@@ -0,0 +1,96 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ import { cn } from '../../lib/utils';
3
+
4
+ interface LoaderIconProps {
5
+ size?: number;
6
+ }
7
+
8
+ const LoaderIcon = ({ size = 16 }: LoaderIconProps) => (
9
+ <svg
10
+ height={size}
11
+ strokeLinejoin="round"
12
+ style={{ color: 'currentcolor' }}
13
+ viewBox="0 0 16 16"
14
+ width={size}
15
+ >
16
+ <title>Loader</title>
17
+ <g clipPath="url(#clip0_2393_1490)">
18
+ <path d="M8 0V4" stroke="currentColor" strokeWidth="1.5" />
19
+ <path
20
+ d="M8 16V12"
21
+ opacity="0.5"
22
+ stroke="currentColor"
23
+ strokeWidth="1.5"
24
+ />
25
+ <path
26
+ d="M3.29773 1.52783L5.64887 4.7639"
27
+ opacity="0.9"
28
+ stroke="currentColor"
29
+ strokeWidth="1.5"
30
+ />
31
+ <path
32
+ d="M12.7023 1.52783L10.3511 4.7639"
33
+ opacity="0.1"
34
+ stroke="currentColor"
35
+ strokeWidth="1.5"
36
+ />
37
+ <path
38
+ d="M12.7023 14.472L10.3511 11.236"
39
+ opacity="0.4"
40
+ stroke="currentColor"
41
+ strokeWidth="1.5"
42
+ />
43
+ <path
44
+ d="M3.29773 14.472L5.64887 11.236"
45
+ opacity="0.6"
46
+ stroke="currentColor"
47
+ strokeWidth="1.5"
48
+ />
49
+ <path
50
+ d="M15.6085 5.52783L11.8043 6.7639"
51
+ opacity="0.2"
52
+ stroke="currentColor"
53
+ strokeWidth="1.5"
54
+ />
55
+ <path
56
+ d="M0.391602 10.472L4.19583 9.23598"
57
+ opacity="0.7"
58
+ stroke="currentColor"
59
+ strokeWidth="1.5"
60
+ />
61
+ <path
62
+ d="M15.6085 10.4722L11.8043 9.2361"
63
+ opacity="0.3"
64
+ stroke="currentColor"
65
+ strokeWidth="1.5"
66
+ />
67
+ <path
68
+ d="M0.391602 5.52783L4.19583 6.7639"
69
+ opacity="0.8"
70
+ stroke="currentColor"
71
+ strokeWidth="1.5"
72
+ />
73
+ </g>
74
+ <defs>
75
+ <clipPath id="clip0_2393_1490">
76
+ <rect fill="white" height="16" width="16" />
77
+ </clipPath>
78
+ </defs>
79
+ </svg>
80
+ );
81
+
82
+ export type LoaderProps = HTMLAttributes<HTMLDivElement> & {
83
+ size?: number;
84
+ };
85
+
86
+ export const Loader = ({ className, size = 16, ...props }: LoaderProps) => (
87
+ <div
88
+ className={cn(
89
+ 'inline-flex animate-spin items-center justify-center',
90
+ className
91
+ )}
92
+ {...props}
93
+ >
94
+ <LoaderIcon size={size} />
95
+ </div>
96
+ );