@chat-js/cli 0.4.0 → 0.6.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/index.js +1163 -959
- package/package.json +1 -1
- package/templates/chat-app/app/(auth)/device-login/page.tsx +37 -0
- package/templates/chat-app/app/(auth)/login/page.tsx +26 -2
- package/templates/chat-app/app/(auth)/register/page.tsx +0 -12
- package/templates/chat-app/app/(chat)/api/chat/filter-reasoning-parts.ts +1 -1
- package/templates/chat-app/app/(chat)/api/chat/route.ts +13 -5
- package/templates/chat-app/app/(chat)/layout.tsx +4 -1
- package/templates/chat-app/app/api/trpc/[trpc]/route.ts +1 -0
- package/templates/chat-app/app/globals.css +9 -9
- package/templates/chat-app/app/layout.tsx +4 -2
- package/templates/chat-app/biome.jsonc +3 -3
- package/templates/chat-app/chat.config.ts +144 -141
- package/templates/chat-app/components/ai-elements/prompt-input.tsx +1 -1
- package/templates/chat-app/components/anonymous-session-init.tsx +10 -6
- package/templates/chat-app/components/artifact-actions.tsx +81 -18
- package/templates/chat-app/components/artifact-panel.tsx +142 -41
- package/templates/chat-app/components/attachment-list.tsx +1 -1
- package/templates/chat-app/components/{social-auth-providers.tsx → auth-providers.tsx} +49 -4
- package/templates/chat-app/components/chat/chat-welcome.tsx +3 -3
- package/templates/chat-app/components/chat-menu-items.tsx +1 -1
- package/templates/chat-app/components/chat-sync.tsx +3 -8
- package/templates/chat-app/components/console.tsx +9 -9
- package/templates/chat-app/components/context-usage.tsx +2 -2
- package/templates/chat-app/components/create-artifact.tsx +15 -5
- package/templates/chat-app/components/data-stream-handler.tsx +57 -16
- package/templates/chat-app/components/device-login-page.tsx +191 -0
- package/templates/chat-app/components/diffview.tsx +8 -2
- package/templates/chat-app/components/electron-auth-handler.tsx +184 -0
- package/templates/chat-app/components/electron-auth-ui.tsx +121 -0
- package/templates/chat-app/components/favicon-group.tsx +1 -1
- package/templates/chat-app/components/feedback-actions.tsx +1 -1
- package/templates/chat-app/components/greeting.tsx +1 -1
- package/templates/chat-app/components/interactive-chart-impl.tsx +3 -4
- package/templates/chat-app/components/interactive-charts.tsx +1 -1
- package/templates/chat-app/components/login-form.tsx +52 -10
- package/templates/chat-app/components/message-editor.tsx +4 -5
- package/templates/chat-app/components/model-selector.tsx +661 -655
- package/templates/chat-app/components/multimodal-input.tsx +13 -10
- package/templates/chat-app/components/parallel-response-cards.tsx +53 -35
- package/templates/chat-app/components/part/code-execution.tsx +8 -2
- package/templates/chat-app/components/part/document-common.tsx +1 -1
- package/templates/chat-app/components/part/document-preview.tsx +5 -5
- package/templates/chat-app/components/part/retrieve-url.tsx +12 -12
- package/templates/chat-app/components/part/text-message-part.tsx +13 -9
- package/templates/chat-app/components/project-chat-item.tsx +1 -1
- package/templates/chat-app/components/project-menu-items.tsx +1 -1
- package/templates/chat-app/components/research-task.tsx +1 -1
- package/templates/chat-app/components/research-tasks.tsx +1 -1
- package/templates/chat-app/components/retry-button.tsx +1 -1
- package/templates/chat-app/components/sandbox.tsx +1 -1
- package/templates/chat-app/components/sheet-editor.tsx +7 -7
- package/templates/chat-app/components/sidebar-chats-list.tsx +1 -1
- package/templates/chat-app/components/sidebar-toggle.tsx +15 -2
- package/templates/chat-app/components/sidebar-top-row.tsx +27 -12
- package/templates/chat-app/components/sidebar-user-nav.tsx +10 -1
- package/templates/chat-app/components/signup-form.tsx +49 -10
- package/templates/chat-app/components/sources.tsx +4 -4
- package/templates/chat-app/components/text-editor.tsx +5 -2
- package/templates/chat-app/components/toolbar.tsx +3 -3
- package/templates/chat-app/components/ui/sidebar.tsx +0 -1
- package/templates/chat-app/components/upgrade-cta/limit-display.tsx +1 -1
- package/templates/chat-app/components/user-message.tsx +135 -134
- package/templates/chat-app/electron.d.ts +41 -0
- package/templates/chat-app/evals/my-eval.eval.ts +3 -1
- package/templates/chat-app/hooks/use-artifact.tsx +13 -13
- package/templates/chat-app/lib/ai/gateways/provider-types.ts +19 -10
- package/templates/chat-app/lib/ai/stream-errors.test.ts +72 -0
- package/templates/chat-app/lib/ai/stream-errors.ts +94 -0
- package/templates/chat-app/lib/ai/tools/code-execution.javascript.ts +171 -0
- package/templates/chat-app/lib/ai/tools/code-execution.python.ts +336 -0
- package/templates/chat-app/lib/ai/tools/code-execution.shared.test.ts +71 -0
- package/templates/chat-app/lib/ai/tools/code-execution.shared.ts +59 -0
- package/templates/chat-app/lib/ai/tools/code-execution.ts +62 -391
- package/templates/chat-app/lib/ai/tools/code-execution.types.ts +24 -0
- package/templates/chat-app/lib/ai/tools/steps/multi-query-web-search.ts +3 -2
- package/templates/chat-app/lib/anonymous-session-client.ts +0 -3
- package/templates/chat-app/lib/artifacts/code/client.tsx +35 -5
- package/templates/chat-app/lib/artifacts/sheet/client.tsx +11 -3
- package/templates/chat-app/lib/auth-client.ts +23 -1
- package/templates/chat-app/lib/auth.ts +18 -1
- package/templates/chat-app/lib/blob.ts +1 -1
- package/templates/chat-app/lib/clone-messages.ts +1 -1
- package/templates/chat-app/lib/config-schema.ts +13 -1
- package/templates/chat-app/lib/constants.ts +3 -4
- package/templates/chat-app/lib/db/migrations/meta/0044_snapshot.json +42 -129
- package/templates/chat-app/lib/db/migrations/meta/_journal.json +1 -1
- package/templates/chat-app/lib/editor/config.ts +4 -4
- package/templates/chat-app/lib/electron-auth.ts +96 -0
- package/templates/chat-app/lib/env-schema.ts +33 -4
- package/templates/chat-app/lib/message-conversion.ts +1 -1
- package/templates/chat-app/lib/playwright-test-environment.ts +18 -0
- package/templates/chat-app/lib/social-auth.ts +5 -0
- package/templates/chat-app/lib/stores/hooks-threads.ts +2 -1
- package/templates/chat-app/lib/stores/with-threads.test.ts +1 -1
- package/templates/chat-app/lib/stores/with-threads.ts +5 -6
- package/templates/chat-app/lib/stores/with-tracing.ts +1 -1
- package/templates/chat-app/lib/thread-utils.ts +19 -21
- package/templates/chat-app/lib/utils/download-assets.ts +6 -7
- package/templates/chat-app/lib/utils/rate-limit.ts +9 -3
- package/templates/chat-app/package.json +20 -18
- package/templates/chat-app/playwright.config.ts +0 -19
- package/templates/chat-app/providers/chat-input-provider.tsx +1 -1
- package/templates/chat-app/proxy.ts +28 -3
- package/templates/chat-app/scripts/check-env.ts +10 -0
- package/templates/chat-app/trpc/server.tsx +7 -2
- package/templates/chat-app/tsconfig.json +2 -1
- package/templates/chat-app/vercel.json +0 -10
- package/templates/electron/CHANGELOG.md +7 -0
- package/templates/electron/README.md +54 -0
- package/templates/electron/entitlements.mac.plist +10 -0
- package/templates/electron/forge.config.ts +157 -0
- package/templates/electron/icon.png +0 -0
- package/templates/electron/package.json +53 -0
- package/templates/electron/scripts/generate-icons.test.js +37 -0
- package/templates/electron/scripts/generate-icons.ts +29 -0
- package/templates/electron/scripts/run-forge.cjs +28 -0
- package/templates/electron/scripts/write-branding.ts +18 -0
- package/templates/electron/src/config.ts +16 -0
- package/templates/electron/src/lib/auth-client.ts +64 -0
- package/templates/electron/src/main.ts +670 -0
- package/templates/electron/src/preload.d.ts +27 -0
- package/templates/electron/src/preload.ts +25 -0
- package/templates/electron/tsconfig.json +18 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import Link from "next/link";
|
|
4
|
-
import {
|
|
4
|
+
import { useSearchParams } from "next/navigation";
|
|
5
|
+
import { Suspense, useEffect, useState } from "react";
|
|
6
|
+
import { SocialAuthProviders } from "@/components/auth-providers";
|
|
5
7
|
import {
|
|
6
8
|
Card,
|
|
7
9
|
CardContent,
|
|
@@ -9,27 +11,64 @@ import {
|
|
|
9
11
|
CardHeader,
|
|
10
12
|
CardTitle,
|
|
11
13
|
} from "@/components/ui/card";
|
|
14
|
+
import {
|
|
15
|
+
buildSocialAuthRequest,
|
|
16
|
+
isElectronRenderer,
|
|
17
|
+
} from "@/lib/electron-auth";
|
|
12
18
|
|
|
13
19
|
export function SignupForm({
|
|
14
20
|
className,
|
|
15
21
|
...props
|
|
16
22
|
}: React.ComponentProps<typeof Card>) {
|
|
23
|
+
const searchParams = useSearchParams();
|
|
24
|
+
const query = Object.fromEntries(searchParams.entries());
|
|
25
|
+
const [isElectron, setIsElectron] = useState(false);
|
|
26
|
+
const { callbackURL, onRedirectToUrl, signInOptions } =
|
|
27
|
+
buildSocialAuthRequest(query, globalThis.location?.origin);
|
|
28
|
+
const loginHref = { pathname: "/login" as const, query };
|
|
29
|
+
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setIsElectron(isElectronRenderer());
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
17
34
|
return (
|
|
18
35
|
<div className="flex flex-col gap-6" {...props}>
|
|
19
36
|
<Card {...props}>
|
|
20
37
|
<CardHeader className="text-center">
|
|
21
|
-
<CardTitle className="text-xl">
|
|
22
|
-
|
|
38
|
+
<CardTitle className="text-xl">
|
|
39
|
+
{isElectron ? "Continue in browser" : "Create an account"}
|
|
40
|
+
</CardTitle>
|
|
41
|
+
<CardDescription>
|
|
42
|
+
{isElectron
|
|
43
|
+
? "Use your browser to sign in or create an account."
|
|
44
|
+
: "Get started in seconds"}
|
|
45
|
+
</CardDescription>
|
|
23
46
|
</CardHeader>
|
|
24
47
|
<CardContent>
|
|
25
48
|
<div className="grid gap-6">
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
49
|
+
<Suspense>
|
|
50
|
+
<SocialAuthProviders
|
|
51
|
+
callbackURL={callbackURL}
|
|
52
|
+
electronBrowserLabel="Continue in browser"
|
|
53
|
+
isElectron={isElectron}
|
|
54
|
+
onRedirectToUrl={onRedirectToUrl}
|
|
55
|
+
query={query}
|
|
56
|
+
signInOptions={signInOptions}
|
|
57
|
+
/>
|
|
58
|
+
</Suspense>
|
|
59
|
+
{isElectron ? (
|
|
60
|
+
<div className="text-center text-muted-foreground text-sm">
|
|
61
|
+
New and existing accounts both continue through the browser
|
|
62
|
+
flow.
|
|
63
|
+
</div>
|
|
64
|
+
) : (
|
|
65
|
+
<div className="text-center text-sm">
|
|
66
|
+
Already have an account?{" "}
|
|
67
|
+
<Link className="underline underline-offset-4" href={loginHref}>
|
|
68
|
+
Sign in
|
|
69
|
+
</Link>
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
33
72
|
</div>
|
|
34
73
|
</CardContent>
|
|
35
74
|
</Card>
|
|
@@ -28,7 +28,7 @@ const SourcesList = ({
|
|
|
28
28
|
<div className="space-y-3">
|
|
29
29
|
{sources?.map((source: SearchResultItem) => (
|
|
30
30
|
<a
|
|
31
|
-
className="block rounded-lg bg-
|
|
31
|
+
className="block rounded-lg bg-secondary p-4 transition-colors hover:bg-accent"
|
|
32
32
|
href={source.url}
|
|
33
33
|
key={source.url}
|
|
34
34
|
rel="noopener noreferrer"
|
|
@@ -113,7 +113,7 @@ function ShowSourcesButton({
|
|
|
113
113
|
}) {
|
|
114
114
|
return (
|
|
115
115
|
<button
|
|
116
|
-
className="group flex items-center justify-center gap-2 rounded-lg border border-
|
|
116
|
+
className="group flex items-center justify-center gap-2 rounded-lg border border-border p-2.5 transition-colors hover:bg-accent"
|
|
117
117
|
onClick={() => document.getElementById(dialogId)?.click()}
|
|
118
118
|
type="button"
|
|
119
119
|
>
|
|
@@ -125,10 +125,10 @@ function ShowSourcesButton({
|
|
|
125
125
|
title: s.title,
|
|
126
126
|
}))}
|
|
127
127
|
/>
|
|
128
|
-
<span className="text-
|
|
128
|
+
<span className="text-muted-foreground text-xs group-hover:text-foreground">
|
|
129
129
|
{sources.length} Sources
|
|
130
130
|
</span>
|
|
131
|
-
<ArrowRight className="h-3.5 w-3.5 text-
|
|
131
|
+
<ArrowRight className="h-3.5 w-3.5 text-muted-foreground transition-colors group-hover:text-foreground" />
|
|
132
132
|
</button>
|
|
133
133
|
);
|
|
134
134
|
}
|
|
@@ -14,6 +14,7 @@ import { ListPlugin } from "@lexical/react/LexicalListPlugin";
|
|
|
14
14
|
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
|
|
15
15
|
import { OnChangePlugin } from "@lexical/react/LexicalOnChangePlugin";
|
|
16
16
|
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
|
|
17
|
+
import type { EditorState } from "lexical";
|
|
17
18
|
import { $getRoot } from "lexical";
|
|
18
19
|
import { memo, useEffect, useRef } from "react";
|
|
19
20
|
|
|
@@ -95,7 +96,7 @@ function ContentUpdatePlugin({
|
|
|
95
96
|
}
|
|
96
97
|
}, [content, status, editor]);
|
|
97
98
|
|
|
98
|
-
const handleChange = (editorState:
|
|
99
|
+
const handleChange = (editorState: EditorState) => {
|
|
99
100
|
if (!(isReadonly || isProgrammaticUpdate.current)) {
|
|
100
101
|
handleEditorChange({
|
|
101
102
|
editorState,
|
|
@@ -129,7 +130,9 @@ function PureEditor({
|
|
|
129
130
|
<ContentEditable className="lexical-editor text-left outline-hidden" />
|
|
130
131
|
}
|
|
131
132
|
ErrorBoundary={LexicalErrorBoundary}
|
|
132
|
-
placeholder={
|
|
133
|
+
placeholder={
|
|
134
|
+
<div className="text-muted-foreground">Start typing...</div>
|
|
135
|
+
}
|
|
133
136
|
/>
|
|
134
137
|
<HistoryPlugin />
|
|
135
138
|
<ListPlugin />
|
|
@@ -89,11 +89,11 @@ function Tool({
|
|
|
89
89
|
return;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
if (selectedTool
|
|
93
|
-
setSelectedTool(description);
|
|
94
|
-
} else {
|
|
92
|
+
if (selectedTool === description) {
|
|
95
93
|
setSelectedTool(null);
|
|
96
94
|
onClick({ sendMessage, storeApi });
|
|
95
|
+
} else {
|
|
96
|
+
setSelectedTool(description);
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
99
|
|
|
@@ -84,7 +84,6 @@ function SidebarProvider({
|
|
|
84
84
|
// This sets the cookie to keep the sidebar state.
|
|
85
85
|
// Prefer Cookie Store API when available
|
|
86
86
|
if ("cookieStore" in window) {
|
|
87
|
-
// @ts-expect-error cookieStore is not yet in TS lib.dom
|
|
88
87
|
void window.cookieStore.set({
|
|
89
88
|
name: SIDEBAR_COOKIE_NAME,
|
|
90
89
|
value: String(openState),
|
|
@@ -11,150 +11,151 @@ import { MessageEditor } from "./message-editor";
|
|
|
11
11
|
import { ParallelResponseCards } from "./parallel-response-cards";
|
|
12
12
|
|
|
13
13
|
export interface BaseMessageProps {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
isReadonly: boolean;
|
|
16
|
+
messageId: string;
|
|
17
|
+
parentMessageId: string | null;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
const PureUserMessage = ({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
messageId,
|
|
22
|
+
isLoading,
|
|
23
|
+
isReadonly,
|
|
24
|
+
parentMessageId,
|
|
25
25
|
}: BaseMessageProps) => {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
const chatId = useChatId();
|
|
27
|
+
const message = useMessageById<ChatMessage>(messageId);
|
|
28
|
+
const [mode, setMode] = useState<"view" | "edit">("view");
|
|
29
|
+
const [imageModal, setImageModal] = useState<{
|
|
30
|
+
isOpen: boolean;
|
|
31
|
+
imageUrl: string;
|
|
32
|
+
imageName?: string;
|
|
33
|
+
}>({ isOpen: false, imageUrl: "" });
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const handleImageClick = (imageUrl: string, imageName?: string) => {
|
|
36
|
+
setImageModal({ isOpen: true, imageUrl, imageName });
|
|
37
|
+
};
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
if (!message) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const textPart = message.parts.find((part) => part.type === "text");
|
|
43
|
+
if (!(textPart && chatId)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<Message
|
|
50
|
+
className={cn(
|
|
51
|
+
// TODO: Consider not using this max-w class override when editing is cohesive with displaying the message
|
|
52
|
+
mode === "edit" ? "max-w-full [&>div]:max-w-full" : undefined,
|
|
53
|
+
"py-1"
|
|
54
|
+
)}
|
|
55
|
+
from="user"
|
|
56
|
+
>
|
|
57
|
+
<div
|
|
58
|
+
className={cn(
|
|
59
|
+
"flex w-full flex-col gap-2",
|
|
60
|
+
message.role === "user" && mode !== "edit" && "items-end"
|
|
61
|
+
)}
|
|
62
|
+
>
|
|
63
|
+
{mode === "view" && <ParallelResponseCards messageId={message.id} />}
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
65
|
+
{mode === "view" && isReadonly && (
|
|
66
|
+
<MessageContent
|
|
67
|
+
className="text-left group-[.is-user]:bg-card"
|
|
68
|
+
data-testid="message-content"
|
|
69
|
+
>
|
|
70
|
+
<AttachmentList
|
|
71
|
+
attachments={getAttachmentsFromMessage(message)}
|
|
72
|
+
onImageClick={handleImageClick}
|
|
73
|
+
testId="message-attachments"
|
|
74
|
+
/>
|
|
75
|
+
<pre className="whitespace-pre-wrap font-sans">
|
|
76
|
+
{textPart.text}
|
|
77
|
+
</pre>
|
|
78
|
+
</MessageContent>
|
|
79
|
+
)}
|
|
80
|
+
{mode === "view" && !isReadonly && (
|
|
81
|
+
<button
|
|
82
|
+
className="block cursor-pointer select-text text-left transition-opacity hover:opacity-80"
|
|
83
|
+
data-testid="message-content"
|
|
84
|
+
onClick={(e) => {
|
|
85
|
+
const selection = window.getSelection();
|
|
86
|
+
if (
|
|
87
|
+
selection?.toString() &&
|
|
88
|
+
e.currentTarget.contains(selection.anchorNode)
|
|
89
|
+
) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
setMode("edit");
|
|
93
|
+
}}
|
|
94
|
+
type="button"
|
|
95
|
+
>
|
|
96
|
+
<MessageContent
|
|
97
|
+
className="text-left group-[.is-user]:max-w-none group-[.is-user]:bg-card"
|
|
98
|
+
data-testid="message-content"
|
|
99
|
+
>
|
|
100
|
+
<AttachmentList
|
|
101
|
+
attachments={getAttachmentsFromMessage(message)}
|
|
102
|
+
onImageClick={handleImageClick}
|
|
103
|
+
testId="message-attachments"
|
|
104
|
+
/>
|
|
105
|
+
<pre className="whitespace-pre-wrap font-sans">
|
|
106
|
+
{textPart.text}
|
|
107
|
+
</pre>
|
|
108
|
+
</MessageContent>
|
|
109
|
+
</button>
|
|
110
|
+
)}
|
|
111
|
+
{mode !== "view" && (
|
|
112
|
+
<div className="flex flex-row items-start gap-2">
|
|
113
|
+
<MessageEditor
|
|
114
|
+
chatId={chatId}
|
|
115
|
+
key={message.id}
|
|
116
|
+
message={message}
|
|
117
|
+
parentMessageId={parentMessageId}
|
|
118
|
+
setMode={setMode}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
)}
|
|
121
122
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
123
|
+
<div className="self-end">
|
|
124
|
+
<MessageActions
|
|
125
|
+
chatId={chatId}
|
|
126
|
+
isEditing={mode === "edit"}
|
|
127
|
+
isLoading={isLoading}
|
|
128
|
+
isReadOnly={isReadonly}
|
|
129
|
+
key={`action-${message.id}`}
|
|
130
|
+
messageId={message.id}
|
|
131
|
+
onCancelEdit={() => setMode("view")}
|
|
132
|
+
onStartEdit={() => setMode("edit")}
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</Message>
|
|
137
|
+
<ImageModal
|
|
138
|
+
imageName={imageModal.imageName}
|
|
139
|
+
imageUrl={imageModal.imageUrl}
|
|
140
|
+
isOpen={imageModal.isOpen}
|
|
141
|
+
onClose={() => setImageModal({ isOpen: false, imageUrl: "" })}
|
|
142
|
+
/>
|
|
143
|
+
</>
|
|
144
|
+
);
|
|
144
145
|
};
|
|
145
146
|
|
|
146
147
|
export const UserMessage = memo(PureUserMessage, (prevProps, nextProps) => {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
148
|
+
if (prevProps.messageId !== nextProps.messageId) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
if (prevProps.isReadonly !== nextProps.isReadonly) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
if (prevProps.parentMessageId !== nextProps.parentMessageId) {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
if (prevProps.isLoading !== nextProps.isLoading) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
160
161
|
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface ElectronAuthErrorContext {
|
|
3
|
+
message?: string;
|
|
4
|
+
path?: string;
|
|
5
|
+
status?: number;
|
|
6
|
+
statusText?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type ElectronRendererAuthState =
|
|
10
|
+
| {
|
|
11
|
+
status: "idle";
|
|
12
|
+
message: null;
|
|
13
|
+
}
|
|
14
|
+
| {
|
|
15
|
+
status: "awaiting-browser" | "finishing" | "timed-out" | "error";
|
|
16
|
+
message: string;
|
|
17
|
+
detail?: string | null;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
interface Window {
|
|
21
|
+
electronAPI?: {
|
|
22
|
+
cancelAuthFlow?: () => Promise<void>;
|
|
23
|
+
getAuthState?: () => Promise<ElectronRendererAuthState>;
|
|
24
|
+
isElectron: boolean;
|
|
25
|
+
onAuthStateChanged?: (
|
|
26
|
+
callback: (state: ElectronRendererAuthState) => void
|
|
27
|
+
) => () => void;
|
|
28
|
+
platform: string;
|
|
29
|
+
syncAuthSession?: () => Promise<void>;
|
|
30
|
+
};
|
|
31
|
+
onAuthError?: (
|
|
32
|
+
callback: (context: ElectronAuthErrorContext) => void
|
|
33
|
+
) => () => void;
|
|
34
|
+
onAuthenticated?: (callback: (user: unknown) => void) => () => void;
|
|
35
|
+
onUserUpdated?: (callback: (user: unknown) => void) => () => void;
|
|
36
|
+
requestAuth?: (options?: { provider?: string }) => Promise<void> | void;
|
|
37
|
+
signOut?: () => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {};
|
|
@@ -16,7 +16,9 @@ evalite("Test Capitals", {
|
|
|
16
16
|
],
|
|
17
17
|
task: async (input) => {
|
|
18
18
|
const result = streamText({
|
|
19
|
-
model: wrapAISDKModel(
|
|
19
|
+
model: wrapAISDKModel(
|
|
20
|
+
openai("gpt-4o-mini") as unknown as Parameters<typeof wrapAISDKModel>[0]
|
|
21
|
+
),
|
|
20
22
|
system: "Answer the question concisely.",
|
|
21
23
|
prompt: input,
|
|
22
24
|
});
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
useState,
|
|
10
10
|
} from "react";
|
|
11
11
|
import type { UIArtifact } from "@/components/artifact-panel";
|
|
12
|
+
import type { ArtifactMetadata } from "@/components/create-artifact";
|
|
12
13
|
|
|
13
14
|
const initialArtifactData: UIArtifact = {
|
|
14
15
|
documentId: "init",
|
|
@@ -23,18 +24,19 @@ const initialArtifactData: UIArtifact = {
|
|
|
23
24
|
|
|
24
25
|
type Selector<T> = (state: UIArtifact) => T;
|
|
25
26
|
|
|
27
|
+
type MetadataUpdater = (current: ArtifactMetadata) => ArtifactMetadata;
|
|
28
|
+
|
|
29
|
+
type MetadataStore = Record<string, ArtifactMetadata>;
|
|
30
|
+
|
|
26
31
|
interface ArtifactContextType {
|
|
27
32
|
artifact: UIArtifact;
|
|
28
|
-
metadata:
|
|
33
|
+
metadata: MetadataStore;
|
|
29
34
|
setArtifact: (
|
|
30
35
|
updaterFn: UIArtifact | ((currentArtifact: UIArtifact) => UIArtifact)
|
|
31
36
|
) => void;
|
|
32
37
|
setMetadata: (
|
|
33
38
|
documentId: string,
|
|
34
|
-
metadata:
|
|
35
|
-
| Record<string, any>
|
|
36
|
-
| null
|
|
37
|
-
| ((current: Record<string, any> | null) => Record<string, any> | null)
|
|
39
|
+
metadata: ArtifactMetadata | MetadataUpdater
|
|
38
40
|
) => void;
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -45,10 +47,7 @@ const ArtifactContext = createContext<ArtifactContextType | undefined>(
|
|
|
45
47
|
export function ArtifactProvider({ children }: { children: ReactNode }) {
|
|
46
48
|
const [artifact, setArtifactState] =
|
|
47
49
|
useState<UIArtifact>(initialArtifactData);
|
|
48
|
-
const [metadataStore, setMetadataStore] = useState<
|
|
49
|
-
string,
|
|
50
|
-
any
|
|
51
|
-
> | null>(initialArtifactData);
|
|
50
|
+
const [metadataStore, setMetadataStore] = useState<MetadataStore>({});
|
|
52
51
|
|
|
53
52
|
const setArtifact = useCallback(
|
|
54
53
|
(updaterFn: UIArtifact | ((currentArtifact: UIArtifact) => UIArtifact)) => {
|
|
@@ -63,12 +62,12 @@ export function ArtifactProvider({ children }: { children: ReactNode }) {
|
|
|
63
62
|
);
|
|
64
63
|
|
|
65
64
|
const setMetadata = useCallback(
|
|
66
|
-
(documentId: string, metadata:
|
|
65
|
+
(documentId: string, metadata: ArtifactMetadata | MetadataUpdater) => {
|
|
67
66
|
setMetadataStore((current) => ({
|
|
68
67
|
...current,
|
|
69
68
|
[documentId]:
|
|
70
69
|
typeof metadata === "function"
|
|
71
|
-
? metadata(current
|
|
70
|
+
? metadata(current[documentId] ?? null)
|
|
72
71
|
: metadata,
|
|
73
72
|
}));
|
|
74
73
|
},
|
|
@@ -117,12 +116,13 @@ export function useArtifact() {
|
|
|
117
116
|
} = useArtifactContext();
|
|
118
117
|
|
|
119
118
|
const metadata = useMemo(
|
|
120
|
-
() =>
|
|
119
|
+
() =>
|
|
120
|
+
artifact.documentId ? (metadataStore[artifact.documentId] ?? null) : null,
|
|
121
121
|
[metadataStore, artifact.documentId]
|
|
122
122
|
);
|
|
123
123
|
|
|
124
124
|
const setMetadata = useCallback(
|
|
125
|
-
(metadataArg:
|
|
125
|
+
(metadataArg: ArtifactMetadata | MetadataUpdater) => {
|
|
126
126
|
if (artifact.documentId) {
|
|
127
127
|
setMetadataStore(artifact.documentId, metadataArg);
|
|
128
128
|
}
|
|
@@ -4,14 +4,23 @@ export type StrictLiterals<T> = T extends string
|
|
|
4
4
|
: T
|
|
5
5
|
: T;
|
|
6
6
|
|
|
7
|
-
export type ExtractModelIdFromProvider<
|
|
8
|
-
ProviderFactory extends (...args:
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
export type ExtractModelIdFromProvider<ProviderFactory> =
|
|
8
|
+
ProviderFactory extends (...args: infer _Args) => infer Provider
|
|
9
|
+
? Provider extends {
|
|
10
|
+
languageModel: (
|
|
11
|
+
modelId: infer ModelId,
|
|
12
|
+
...args: infer _Rest
|
|
13
|
+
) => unknown;
|
|
14
|
+
}
|
|
15
|
+
? ModelId
|
|
16
|
+
: never
|
|
17
|
+
: never;
|
|
12
18
|
|
|
13
|
-
export type ExtractImageModelIdFromProvider<
|
|
14
|
-
ProviderFactory extends (...args:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
export type ExtractImageModelIdFromProvider<ProviderFactory> =
|
|
20
|
+
ProviderFactory extends (...args: infer _Args) => infer Provider
|
|
21
|
+
? Provider extends {
|
|
22
|
+
image: (modelId: infer ModelId, ...args: infer _Rest) => unknown;
|
|
23
|
+
}
|
|
24
|
+
? ModelId
|
|
25
|
+
: never
|
|
26
|
+
: never;
|