@chat-js/cli 0.1.4 → 0.2.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/dist/index.js +394 -247
- package/package.json +48 -48
- package/templates/chat-app/.claude/skiller.toml +18 -0
- package/templates/chat-app/.claude/skills/chat-context/SKILL.md +6 -0
- package/templates/chat-app/.claude/skills/chat-context/chat-context.mdc +36 -0
- package/templates/chat-app/.claude/skills/lazy-prefetch-pattern/lazy-prefetch-pattern.mdc +27 -0
- package/templates/chat-app/.claude/skills/react/react.mdc +29 -0
- package/templates/chat-app/.claude/skills/trpc-patterns/trpc-patterns.mdc +77 -0
- package/templates/chat-app/.claude/skills/typescript/typescript.mdc +53 -0
- package/templates/chat-app/.claude/skills/ultracite/ultracite.mdc +129 -0
- package/templates/chat-app/.cursor/skills/chat-context/SKILL.md +37 -0
- package/templates/chat-app/.cursor/skills/lazy-prefetch-pattern/SKILL.md +26 -0
- package/templates/chat-app/.cursor/skills/react/SKILL.md +28 -0
- package/templates/chat-app/.cursor/skills/trpc-patterns/SKILL.md +76 -0
- package/templates/chat-app/.cursor/skills/typescript/SKILL.md +52 -0
- package/templates/chat-app/.cursor/skills/ultracite/SKILL.md +128 -0
- package/templates/chat-app/app/(chat)/actions.ts +17 -13
- package/templates/chat-app/app/(chat)/api/chat/[id]/stream/route.ts +6 -5
- package/templates/chat-app/app/(chat)/api/chat/route.ts +14 -15
- package/templates/chat-app/app/(chat)/chat-providers.tsx +2 -2
- package/templates/chat-app/app/(chat)/layout.tsx +7 -6
- package/templates/chat-app/app/api/cron/cleanup/route.ts +4 -3
- package/templates/chat-app/app/globals.css +23 -23
- package/templates/chat-app/app/layout.tsx +1 -1
- package/templates/chat-app/biome.jsonc +3 -3
- package/templates/chat-app/chat.config.ts +48 -21
- package/templates/chat-app/components/anonymous-session-init.tsx +4 -12
- package/templates/chat-app/components/artifact-actions.tsx +5 -5
- package/templates/chat-app/components/artifact-panel.tsx +6 -6
- package/templates/chat-app/components/assistant-message.tsx +1 -1
- package/templates/chat-app/components/chat/chat-layout.tsx +2 -2
- package/templates/chat-app/components/chat/chat-welcome.tsx +1 -0
- package/templates/chat-app/components/chat-features-definitions.ts +11 -8
- package/templates/chat-app/components/chat-menu-items.tsx +4 -4
- package/templates/chat-app/components/chat-sync.tsx +1 -1
- package/templates/chat-app/components/clone-chat-button.tsx +2 -2
- package/templates/chat-app/components/code-editor.tsx +5 -5
- package/templates/chat-app/components/connectors-dropdown.tsx +2 -2
- package/templates/chat-app/components/console.tsx +5 -5
- package/templates/chat-app/components/create-artifact.tsx +28 -28
- package/templates/chat-app/components/data-stream-provider.tsx +2 -2
- package/templates/chat-app/components/deep-research-progress.tsx +2 -2
- package/templates/chat-app/components/delete-chat-dialog.tsx +3 -3
- package/templates/chat-app/components/delete-project-dialog.tsx +3 -3
- package/templates/chat-app/components/diffview.tsx +3 -3
- package/templates/chat-app/components/favicon-group.tsx +7 -7
- package/templates/chat-app/components/header-breadcrumb.tsx +11 -11
- package/templates/chat-app/components/image-editor.tsx +5 -5
- package/templates/chat-app/components/image-modal.tsx +4 -4
- package/templates/chat-app/components/interactive-chart-impl.tsx +269 -0
- package/templates/chat-app/components/interactive-charts.tsx +18 -246
- package/templates/chat-app/components/lexical-chat-input.tsx +10 -10
- package/templates/chat-app/components/message-editor.tsx +3 -3
- package/templates/chat-app/components/message-parts.tsx +8 -3
- package/templates/chat-app/components/messages-pane.tsx +4 -4
- package/templates/chat-app/components/messages.tsx +5 -5
- package/templates/chat-app/components/model-selector.tsx +4 -1
- package/templates/chat-app/components/multimodal-input.tsx +14 -5
- package/templates/chat-app/components/part/code-execution.tsx +4 -1
- package/templates/chat-app/components/part/document-common.tsx +8 -8
- package/templates/chat-app/components/part/document-preview.tsx +34 -16
- package/templates/chat-app/components/part/document-tool.tsx +3 -3
- package/templates/chat-app/components/part/dynamic-tool.tsx +3 -3
- package/templates/chat-app/components/part/generate-video.tsx +54 -0
- package/templates/chat-app/components/part/message-reasoning.tsx +3 -3
- package/templates/chat-app/components/project-details-dialog.tsx +4 -4
- package/templates/chat-app/components/project-home.tsx +1 -0
- package/templates/chat-app/components/project-icon-picker.tsx +5 -5
- package/templates/chat-app/components/project-icon.tsx +4 -4
- package/templates/chat-app/components/project-menu-items.tsx +3 -3
- package/templates/chat-app/components/research-tasks.tsx +3 -3
- package/templates/chat-app/components/sandbox.tsx +4 -4
- package/templates/chat-app/components/search-chats-dialog.tsx +11 -11
- package/templates/chat-app/components/settings/connectors-settings.tsx +1 -1
- package/templates/chat-app/components/settings/settings-nav.tsx +1 -1
- package/templates/chat-app/components/sheet-editor.tsx +5 -5
- package/templates/chat-app/components/sidebar-chats-list.tsx +5 -5
- package/templates/chat-app/components/suggested-actions.tsx +3 -3
- package/templates/chat-app/components/text-editor.tsx +5 -5
- package/templates/chat-app/components/toolbar.tsx +6 -6
- package/templates/chat-app/components/upgrade-cta/login-cta-banner.tsx +5 -5
- package/templates/chat-app/components/upgrade-cta/login-prompt.tsx +4 -4
- package/templates/chat-app/components/upgrade-cta/share-menu-item.tsx +3 -3
- package/templates/chat-app/components/user-message.tsx +3 -3
- package/templates/chat-app/components/version-footer.tsx +4 -4
- package/templates/chat-app/hooks/chat-sync-hooks.ts +0 -55
- package/templates/chat-app/hooks/use-artifact.tsx +3 -3
- package/templates/chat-app/hooks/use-auto-focus.ts +37 -7
- package/templates/chat-app/hooks/use-media-query.tsx +2 -4
- package/templates/chat-app/lib/ai/active-gateway.ts +1 -1
- package/templates/chat-app/lib/ai/ai-gateway-models-schemas.ts +30 -6
- package/templates/chat-app/lib/ai/app-model-id.ts +1 -1
- package/templates/chat-app/lib/ai/app-models.ts +4 -4
- package/templates/chat-app/lib/ai/eval-agent.ts +5 -5
- package/templates/chat-app/lib/ai/followup-suggestions.ts +5 -2
- package/templates/chat-app/lib/ai/gateway-model-defaults.ts +131 -41
- package/templates/chat-app/lib/ai/gateways/gateway-provider.ts +10 -6
- package/templates/chat-app/lib/ai/gateways/openai-compatible-gateway.ts +9 -4
- package/templates/chat-app/lib/ai/gateways/openai-gateway.ts +9 -4
- package/templates/chat-app/lib/ai/gateways/openrouter-gateway.ts +17 -12
- package/templates/chat-app/lib/ai/gateways/registry.ts +9 -0
- package/templates/chat-app/lib/ai/gateways/vercel-gateway.ts +36 -4
- package/templates/chat-app/lib/ai/mcp/cache.ts +13 -13
- package/templates/chat-app/lib/ai/model-data.ts +21 -20
- package/templates/chat-app/lib/ai/models.generated.ts +4397 -3592
- package/templates/chat-app/lib/ai/models.ts +1 -1
- package/templates/chat-app/lib/ai/providers.ts +10 -0
- package/templates/chat-app/lib/ai/text-splitter.ts +3 -4
- package/templates/chat-app/lib/ai/to-model-data.ts +1 -0
- package/templates/chat-app/lib/ai/tools/code-execution.ts +122 -53
- package/templates/chat-app/lib/ai/tools/deep-research/configuration.ts +35 -32
- package/templates/chat-app/lib/ai/tools/deep-research/pipeline.ts +2 -2
- package/templates/chat-app/lib/ai/tools/deep-research/types.ts +9 -9
- package/templates/chat-app/lib/ai/tools/documents/types.ts +4 -4
- package/templates/chat-app/lib/ai/tools/generate-image.ts +42 -20
- package/templates/chat-app/lib/ai/tools/generate-video.ts +166 -0
- package/templates/chat-app/lib/ai/tools/get-weather.ts +20 -20
- package/templates/chat-app/lib/ai/tools/read-document.ts +3 -3
- package/templates/chat-app/lib/ai/tools/steps/multi-query-web-search.ts +11 -11
- package/templates/chat-app/lib/ai/tools/steps/web-search.ts +6 -6
- package/templates/chat-app/lib/ai/tools/tools-definitions.ts +10 -5
- package/templates/chat-app/lib/ai/tools/tools.ts +15 -6
- package/templates/chat-app/lib/ai/tools/types.ts +2 -2
- package/templates/chat-app/lib/ai/types.ts +22 -13
- package/templates/chat-app/lib/artifacts/code/client.tsx +5 -5
- package/templates/chat-app/lib/artifacts/sheet/client.tsx +2 -2
- package/templates/chat-app/lib/artifacts/text/client.tsx +18 -3
- package/templates/chat-app/lib/clone-messages.test.ts +6 -1
- package/templates/chat-app/lib/config-requirements.ts +19 -10
- package/templates/chat-app/lib/config-schema.ts +189 -103
- package/templates/chat-app/lib/config.ts +4 -4
- package/templates/chat-app/lib/credits/cost-accumulator.ts +11 -8
- package/templates/chat-app/lib/env-schema.ts +1 -1
- package/templates/chat-app/lib/features-config.ts +6 -6
- package/templates/chat-app/lib/stores/with-threads.ts +3 -3
- package/templates/chat-app/lib/thread-utils.ts +2 -2
- package/templates/chat-app/lib/types/anonymous.ts +4 -4
- package/templates/chat-app/lib/types/ui-chat.ts +7 -7
- package/templates/chat-app/lib/utils/download-assets.ts +3 -3
- package/templates/chat-app/lib/utils/rate-limit.ts +8 -8
- package/templates/chat-app/next.config.ts +0 -25
- package/templates/chat-app/package.json +16 -16
- package/templates/chat-app/playwright.config.ts +5 -5
- package/templates/chat-app/providers/chat-id-provider.tsx +5 -5
- package/templates/chat-app/providers/chat-input-provider.tsx +15 -15
- package/templates/chat-app/providers/chat-models-provider.tsx +3 -3
- package/templates/chat-app/providers/default-model-provider.tsx +5 -5
- package/templates/chat-app/providers/parse-chat-id-from-pathname.test.ts +16 -0
- package/templates/chat-app/providers/session-provider.tsx +2 -2
- package/templates/chat-app/scripts/check-env.ts +36 -4
- package/templates/chat-app/tests/artifacts.e2e.ts +7 -0
- package/templates/chat-app/tests/auth.setup.e2e.ts +10 -0
- package/templates/chat-app/tests/chat.e2e.ts +7 -0
- package/templates/chat-app/tests/reasoning.e2e.ts +7 -0
- package/templates/chat-app/tests/reasoning.setup.e2e.ts +10 -0
- package/templates/chat-app/trpc/routers/chat.router.ts +1 -1
- package/templates/chat-app/trpc/routers/mcp.router.ts +3 -3
- package/templates/chat-app/vitest.config.ts +7 -0
- package/templates/chat-app/next-env.d.ts +0 -6
- package/templates/chat-app/tsconfig.tsbuildinfo +0 -1
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
"analyze": "next experimental-analyze",
|
|
12
12
|
"start": "next start",
|
|
13
13
|
"prod": "bun run build && bun run start",
|
|
14
|
-
"lint": "bunx ultracite@
|
|
15
|
-
"format": "bunx ultracite@
|
|
14
|
+
"lint": "bunx ultracite@7.2.3 check",
|
|
15
|
+
"format": "bunx ultracite@7.2.3 fix",
|
|
16
16
|
"check-env": "bun scripts/check-env.ts",
|
|
17
17
|
"db:generate": "drizzle-kit generate",
|
|
18
18
|
"db:migrate": "export VERCEL_ENV=production && bash scripts/with-db.sh bunx tsx lib/db/migrate.ts",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"eval:dev": "evalite watch",
|
|
32
32
|
"eval:serve": "evalite serve",
|
|
33
33
|
"skiller:apply": "bunx skiller@latest apply",
|
|
34
|
-
"test": "bun test:
|
|
35
|
-
"test:
|
|
34
|
+
"test": "bun test:e2e && bun test:unit",
|
|
35
|
+
"test:e2e": "export PLAYWRIGHT=True && bunx playwright test --workers=4",
|
|
36
36
|
"test:unit": "vitest run",
|
|
37
37
|
"test:types": "rm -rf .next/dev/types && next typegen . && tsc --noEmit",
|
|
38
38
|
"ai:devtools": "bunx @ai-sdk/devtools",
|
|
@@ -40,15 +40,15 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@ai-sdk-tools/store": "1.2.0",
|
|
43
|
-
"@ai-sdk/anthropic": "3.0.
|
|
44
|
-
"@ai-sdk/devtools": "0.0.
|
|
45
|
-
"@ai-sdk/gateway": "3.0.
|
|
46
|
-
"@ai-sdk/google": "3.0.
|
|
47
|
-
"@ai-sdk/mcp": "1.0.
|
|
48
|
-
"@ai-sdk/openai": "3.0.
|
|
49
|
-
"@ai-sdk/openai-compatible": "^2.0.
|
|
50
|
-
"@ai-sdk/provider": "3.0.
|
|
51
|
-
"@ai-sdk/react": "3.0.
|
|
43
|
+
"@ai-sdk/anthropic": "^3.0.46",
|
|
44
|
+
"@ai-sdk/devtools": "^0.0.15",
|
|
45
|
+
"@ai-sdk/gateway": "3.0.53",
|
|
46
|
+
"@ai-sdk/google": "^3.0.30",
|
|
47
|
+
"@ai-sdk/mcp": "^1.0.21",
|
|
48
|
+
"@ai-sdk/openai": "^3.0.30",
|
|
49
|
+
"@ai-sdk/openai-compatible": "^2.0.30",
|
|
50
|
+
"@ai-sdk/provider": "3.0.8",
|
|
51
|
+
"@ai-sdk/react": "^3.0.99",
|
|
52
52
|
"@codemirror/lang-javascript": "^6.2.2",
|
|
53
53
|
"@codemirror/lang-python": "^6.1.6",
|
|
54
54
|
"@codemirror/state": "^6.5.0",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"@radix-ui/react-toggle": "^1.1.10",
|
|
89
89
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
90
90
|
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
|
91
|
-
"@streamdown/code": "^1.0.
|
|
91
|
+
"@streamdown/code": "^1.0.3",
|
|
92
92
|
"@streamdown/math": "^1.0.2",
|
|
93
93
|
"@streamdown/mermaid": "^1.0.2",
|
|
94
94
|
"@t3-oss/env-nextjs": "^0.13.8",
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"@vercel/otel": "^2.1.0",
|
|
105
105
|
"@vercel/sandbox": "^1.0.2",
|
|
106
106
|
"@vercel/speed-insights": "^1.3.1",
|
|
107
|
-
"ai": "6.0.
|
|
107
|
+
"ai": "6.0.97",
|
|
108
108
|
"better-auth": "^1.4.3",
|
|
109
109
|
"browser-image-compression": "^2.0.2",
|
|
110
110
|
"class-variance-authority": "^0.7.1",
|
|
@@ -179,7 +179,7 @@
|
|
|
179
179
|
"tsx": "^4.19.1",
|
|
180
180
|
"tw-animate-css": "^1.3.7",
|
|
181
181
|
"typescript": "5.8.3",
|
|
182
|
-
"ultracite": "
|
|
182
|
+
"ultracite": "7.2.3",
|
|
183
183
|
"vite-tsconfig-paths": "^6.1.1",
|
|
184
184
|
"vitest": "^4.0.0"
|
|
185
185
|
}
|
|
@@ -53,11 +53,11 @@ export default defineConfig({
|
|
|
53
53
|
projects: [
|
|
54
54
|
{
|
|
55
55
|
name: "setup:auth",
|
|
56
|
-
testMatch: /auth.setup.ts/,
|
|
56
|
+
testMatch: /auth.setup.e2e.ts/,
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
name: "setup:reasoning",
|
|
60
|
-
testMatch: /reasoning.setup.ts/,
|
|
60
|
+
testMatch: /reasoning.setup.e2e.ts/,
|
|
61
61
|
dependencies: ["setup:auth"],
|
|
62
62
|
use: {
|
|
63
63
|
...devices["Desktop Chrome"],
|
|
@@ -66,7 +66,7 @@ export default defineConfig({
|
|
|
66
66
|
},
|
|
67
67
|
{
|
|
68
68
|
name: "chat",
|
|
69
|
-
testMatch: /chat.
|
|
69
|
+
testMatch: /chat.e2e.ts/,
|
|
70
70
|
dependencies: ["setup:auth"],
|
|
71
71
|
use: {
|
|
72
72
|
...devices["Desktop Chrome"],
|
|
@@ -75,7 +75,7 @@ export default defineConfig({
|
|
|
75
75
|
},
|
|
76
76
|
{
|
|
77
77
|
name: "reasoning",
|
|
78
|
-
testMatch: /reasoning.
|
|
78
|
+
testMatch: /reasoning.e2e.ts/,
|
|
79
79
|
dependencies: ["setup:reasoning"],
|
|
80
80
|
use: {
|
|
81
81
|
...devices["Desktop Chrome"],
|
|
@@ -84,7 +84,7 @@ export default defineConfig({
|
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
name: "artifacts",
|
|
87
|
-
testMatch: /artifacts.
|
|
87
|
+
testMatch: /artifacts.e2e.ts/,
|
|
88
88
|
dependencies: ["setup:auth"],
|
|
89
89
|
use: {
|
|
90
90
|
...devices["Desktop Chrome"],
|
|
@@ -16,14 +16,14 @@ import {
|
|
|
16
16
|
parseChatIdFromPathname,
|
|
17
17
|
} from "./parse-chat-id-from-pathname";
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
interface ChatIdContextType {
|
|
20
|
+
confirmChatId: (chatId: string) => void;
|
|
20
21
|
id: string;
|
|
21
|
-
type: ChatIdType;
|
|
22
|
-
source: ParsedChatIdFromPathname["source"];
|
|
23
22
|
isPersisted: boolean;
|
|
24
|
-
confirmChatId: (chatId: string) => void;
|
|
25
23
|
refreshChatID: () => void;
|
|
26
|
-
|
|
24
|
+
source: ParsedChatIdFromPathname["source"];
|
|
25
|
+
type: ChatIdType;
|
|
26
|
+
}
|
|
27
27
|
|
|
28
28
|
const ChatIdContext = createContext<ChatIdContextType | undefined>(undefined);
|
|
29
29
|
|
|
@@ -17,35 +17,35 @@ import type { Attachment, UiToolName } from "@/lib/ai/types";
|
|
|
17
17
|
import { useChatModels } from "./chat-models-provider";
|
|
18
18
|
import { useDefaultModel, useModelChange } from "./default-model-provider";
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
editorRef: React.RefObject<LexicalChatInputRef | null>;
|
|
22
|
-
selectedTool: UiToolName | null;
|
|
23
|
-
setSelectedTool: Dispatch<SetStateAction<UiToolName | null>>;
|
|
20
|
+
interface ChatInputContextType {
|
|
24
21
|
attachments: Attachment[];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
handleModelChange: (modelId: AppModelId) => Promise<void>;
|
|
22
|
+
editorRef: React.RefObject<LexicalChatInputRef | null>;
|
|
23
|
+
getInitialInput: () => string;
|
|
28
24
|
getInputValue: () => string;
|
|
29
25
|
handleInputChange: (value: string) => void;
|
|
30
|
-
|
|
31
|
-
isEmpty: boolean;
|
|
26
|
+
handleModelChange: (modelId: AppModelId) => Promise<void>;
|
|
32
27
|
handleSubmit: (submitFn: () => void, isEditMode?: boolean) => void;
|
|
28
|
+
isEmpty: boolean;
|
|
33
29
|
isProjectContext: boolean;
|
|
34
|
-
|
|
30
|
+
selectedModelId: AppModelId;
|
|
31
|
+
selectedTool: UiToolName | null;
|
|
32
|
+
setAttachments: Dispatch<SetStateAction<Attachment[]>>;
|
|
33
|
+
setSelectedTool: Dispatch<SetStateAction<UiToolName | null>>;
|
|
34
|
+
}
|
|
35
35
|
|
|
36
36
|
const ChatInputContext = createContext<ChatInputContextType | undefined>(
|
|
37
37
|
undefined
|
|
38
38
|
);
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
interface ChatInputProviderProps {
|
|
41
41
|
children: ReactNode;
|
|
42
|
+
initialAttachments?: Attachment[];
|
|
42
43
|
initialInput?: string;
|
|
43
44
|
initialTool?: UiToolName | null;
|
|
44
|
-
initialAttachments?: Attachment[];
|
|
45
|
-
overrideModelId?: AppModelId; // For message editing where we want to use the original model
|
|
46
|
-
localStorageEnabled?: boolean;
|
|
47
45
|
isProjectContext?: boolean;
|
|
48
|
-
|
|
46
|
+
localStorageEnabled?: boolean;
|
|
47
|
+
overrideModelId?: AppModelId; // For message editing where we want to use the original model
|
|
48
|
+
}
|
|
49
49
|
|
|
50
50
|
export function ChatInputProvider({
|
|
51
51
|
children,
|
|
@@ -16,11 +16,11 @@ import {
|
|
|
16
16
|
import { useSession } from "@/providers/session-provider";
|
|
17
17
|
import { useTRPC } from "@/trpc/react";
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
models: AppModelDefinition[];
|
|
19
|
+
interface ChatModelsContextType {
|
|
21
20
|
allModels: AppModelDefinition[];
|
|
22
21
|
getModelById: (modelId: string) => AppModelDefinition | undefined;
|
|
23
|
-
|
|
22
|
+
models: AppModelDefinition[];
|
|
23
|
+
}
|
|
24
24
|
|
|
25
25
|
const ChatModelsContext = createContext<ChatModelsContextType | undefined>(
|
|
26
26
|
undefined
|
|
@@ -11,19 +11,19 @@ import {
|
|
|
11
11
|
import { toast } from "sonner";
|
|
12
12
|
import type { AppModelId } from "@/lib/ai/app-models";
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
defaultModel: AppModelId;
|
|
14
|
+
interface DefaultModelContextType {
|
|
16
15
|
changeModel: (modelId: AppModelId) => Promise<void>;
|
|
17
|
-
|
|
16
|
+
defaultModel: AppModelId;
|
|
17
|
+
}
|
|
18
18
|
|
|
19
19
|
const DefaultModelContext = createContext<DefaultModelContextType | undefined>(
|
|
20
20
|
undefined
|
|
21
21
|
);
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
interface DefaultModelClientProviderProps {
|
|
24
24
|
children: ReactNode;
|
|
25
25
|
defaultModel: AppModelId;
|
|
26
|
-
}
|
|
26
|
+
}
|
|
27
27
|
|
|
28
28
|
export function DefaultModelProvider({
|
|
29
29
|
children,
|
|
@@ -7,6 +7,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
7
7
|
expect(parseChatIdFromPathname("/share/abc-123")).toEqual({
|
|
8
8
|
type: "chat",
|
|
9
9
|
id: "abc-123",
|
|
10
|
+
source: "share",
|
|
11
|
+
projectId: null,
|
|
10
12
|
});
|
|
11
13
|
});
|
|
12
14
|
|
|
@@ -14,6 +16,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
14
16
|
expect(parseChatIdFromPathname("/share/abc-123-def-456")).toEqual({
|
|
15
17
|
type: "chat",
|
|
16
18
|
id: "abc-123-def-456",
|
|
19
|
+
source: "share",
|
|
20
|
+
projectId: null,
|
|
17
21
|
});
|
|
18
22
|
});
|
|
19
23
|
});
|
|
@@ -23,6 +27,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
23
27
|
expect(parseChatIdFromPathname("/project/proj-123")).toEqual({
|
|
24
28
|
type: "provisional",
|
|
25
29
|
id: null,
|
|
30
|
+
source: "project",
|
|
31
|
+
projectId: "proj-123",
|
|
26
32
|
});
|
|
27
33
|
});
|
|
28
34
|
|
|
@@ -32,6 +38,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
32
38
|
).toEqual({
|
|
33
39
|
type: "chat",
|
|
34
40
|
id: "chat-456",
|
|
41
|
+
source: "project",
|
|
42
|
+
projectId: "proj-123",
|
|
35
43
|
});
|
|
36
44
|
});
|
|
37
45
|
});
|
|
@@ -41,6 +49,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
41
49
|
expect(parseChatIdFromPathname("/chat/chat-789")).toEqual({
|
|
42
50
|
type: "chat",
|
|
43
51
|
id: "chat-789",
|
|
52
|
+
source: "chat",
|
|
53
|
+
projectId: null,
|
|
44
54
|
});
|
|
45
55
|
});
|
|
46
56
|
});
|
|
@@ -50,6 +60,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
50
60
|
expect(parseChatIdFromPathname("/")).toEqual({
|
|
51
61
|
type: "provisional",
|
|
52
62
|
id: null,
|
|
63
|
+
source: "home",
|
|
64
|
+
projectId: null,
|
|
53
65
|
});
|
|
54
66
|
});
|
|
55
67
|
|
|
@@ -57,6 +69,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
57
69
|
expect(parseChatIdFromPathname(null)).toEqual({
|
|
58
70
|
type: "provisional",
|
|
59
71
|
id: null,
|
|
72
|
+
source: "home",
|
|
73
|
+
projectId: null,
|
|
60
74
|
});
|
|
61
75
|
});
|
|
62
76
|
|
|
@@ -64,6 +78,8 @@ describe("parseChatIdFromPathname", () => {
|
|
|
64
78
|
expect(parseChatIdFromPathname("/settings")).toEqual({
|
|
65
79
|
type: "provisional",
|
|
66
80
|
id: null,
|
|
81
|
+
source: "home",
|
|
82
|
+
projectId: null,
|
|
67
83
|
});
|
|
68
84
|
});
|
|
69
85
|
});
|
|
@@ -4,10 +4,10 @@ import { createContext, useContext, useMemo } from "react";
|
|
|
4
4
|
import type { Session } from "@/lib/auth";
|
|
5
5
|
import authClient from "@/lib/auth-client";
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
interface SessionContextValue {
|
|
8
8
|
data: Session | null;
|
|
9
9
|
isPending: boolean;
|
|
10
|
-
}
|
|
10
|
+
}
|
|
11
11
|
|
|
12
12
|
const SessionContext = createContext<SessionContextValue | undefined>(
|
|
13
13
|
undefined
|
|
@@ -9,6 +9,7 @@ import type { GatewayType } from "../lib/ai/gateways/registry";
|
|
|
9
9
|
import { generatedForGateway } from "../lib/ai/models.generated";
|
|
10
10
|
import { config } from "../lib/config";
|
|
11
11
|
import {
|
|
12
|
+
aiToolEnvRequirements,
|
|
12
13
|
authEnvRequirements,
|
|
13
14
|
featureEnvRequirements,
|
|
14
15
|
gatewayEnvRequirements,
|
|
@@ -16,11 +17,14 @@ import {
|
|
|
16
17
|
isRequirementSatisfied,
|
|
17
18
|
} from "../lib/config-requirements";
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
interface ValidationError {
|
|
21
|
+
feature: string;
|
|
22
|
+
missing: string[];
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
function validateGatewayKey(env: NodeJS.ProcessEnv): ValidationError | null {
|
|
22
26
|
// Prevent TS from narrowing to the current literal config value.
|
|
23
|
-
const gateway = (() => config.
|
|
27
|
+
const gateway = (() => config.ai.gateway as GatewayType)();
|
|
24
28
|
const requirement = gatewayEnvRequirements[gateway];
|
|
25
29
|
const missing = getMissingRequirement(requirement, env);
|
|
26
30
|
if (!missing) {
|
|
@@ -62,6 +66,33 @@ function validateFeatures(env: NodeJS.ProcessEnv): ValidationError[] {
|
|
|
62
66
|
return errors;
|
|
63
67
|
}
|
|
64
68
|
|
|
69
|
+
function validateAiTools(env: NodeJS.ProcessEnv): ValidationError[] {
|
|
70
|
+
const errors: ValidationError[] = [];
|
|
71
|
+
|
|
72
|
+
const toolEntries = Object.entries(aiToolEnvRequirements) as [
|
|
73
|
+
keyof typeof aiToolEnvRequirements,
|
|
74
|
+
NonNullable<
|
|
75
|
+
(typeof aiToolEnvRequirements)[keyof typeof aiToolEnvRequirements]
|
|
76
|
+
>,
|
|
77
|
+
][];
|
|
78
|
+
|
|
79
|
+
for (const [tool, requirement] of toolEntries) {
|
|
80
|
+
const toolConfig = config.ai.tools[tool];
|
|
81
|
+
if (!(requirement && "enabled" in toolConfig && toolConfig.enabled)) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const missing = getMissingRequirement(requirement, env);
|
|
85
|
+
if (missing) {
|
|
86
|
+
errors.push({
|
|
87
|
+
feature: `ai.tools.${tool}`,
|
|
88
|
+
missing: [missing],
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return errors;
|
|
94
|
+
}
|
|
95
|
+
|
|
65
96
|
function validateAuthentication(env: NodeJS.ProcessEnv): ValidationError[] {
|
|
66
97
|
const errors: ValidationError[] = [];
|
|
67
98
|
|
|
@@ -119,10 +150,10 @@ function validateBaseUrl(env: NodeJS.ProcessEnv): ValidationError | null {
|
|
|
119
150
|
}
|
|
120
151
|
|
|
121
152
|
function checkGatewaySnapshot(): string | null {
|
|
122
|
-
if (config.
|
|
153
|
+
if (config.ai.gateway === generatedForGateway) {
|
|
123
154
|
return null;
|
|
124
155
|
}
|
|
125
|
-
return `models.generated.ts was built for "${generatedForGateway}" but config uses "${config.
|
|
156
|
+
return `models.generated.ts was built for "${generatedForGateway}" but config uses "${config.ai.gateway}". Run \`bun fetch:models\` to update the fallback snapshot.`;
|
|
126
157
|
}
|
|
127
158
|
|
|
128
159
|
function checkEnv(): void {
|
|
@@ -131,6 +162,7 @@ function checkEnv(): void {
|
|
|
131
162
|
const errors = [
|
|
132
163
|
...(baseUrlError ? [baseUrlError] : []),
|
|
133
164
|
...validateFeatures(env),
|
|
165
|
+
...validateAiTools(env),
|
|
134
166
|
...validateAuthentication(env),
|
|
135
167
|
];
|
|
136
168
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { test as setup } from "@playwright/test";
|
|
3
|
+
|
|
4
|
+
const authFile = path.resolve("playwright/.auth/session.json");
|
|
5
|
+
|
|
6
|
+
setup("authenticate", async ({ page }) => {
|
|
7
|
+
await page.goto("/api/dev-login");
|
|
8
|
+
await page.waitForURL("/");
|
|
9
|
+
await page.context().storageState({ path: authFile });
|
|
10
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { test as setup } from "@playwright/test";
|
|
3
|
+
|
|
4
|
+
const reasoningFile = path.resolve("playwright/.reasoning/session.json");
|
|
5
|
+
|
|
6
|
+
setup("authenticate for reasoning", async ({ page }) => {
|
|
7
|
+
await page.goto("/api/dev-login");
|
|
8
|
+
await page.waitForURL("/");
|
|
9
|
+
await page.context().storageState({ path: reasoningFile });
|
|
10
|
+
});
|
|
@@ -295,7 +295,7 @@ export const chatRouter = createTRPCRouter({
|
|
|
295
295
|
)
|
|
296
296
|
.mutation(async ({ input }) => {
|
|
297
297
|
const { text: title } = await generateText({
|
|
298
|
-
model: await getLanguageModel(config.
|
|
298
|
+
model: await getLanguageModel(config.ai.workflows.title),
|
|
299
299
|
system: `\n
|
|
300
300
|
- you will generate a short title based on the first message a user begins a conversation with
|
|
301
301
|
- ensure it is not more than 80 characters long
|
|
@@ -26,7 +26,7 @@ import { createTRPCRouter, protectedProcedure } from "@/trpc/init";
|
|
|
26
26
|
const log = createModuleLogger("mcp.router");
|
|
27
27
|
|
|
28
28
|
function assertMcpEnabled() {
|
|
29
|
-
if (!config.
|
|
29
|
+
if (!config.ai.tools.mcp.enabled) {
|
|
30
30
|
throw new TRPCError({
|
|
31
31
|
code: "PRECONDITION_FAILED",
|
|
32
32
|
message: "MCP integration disabled",
|
|
@@ -113,7 +113,7 @@ async function getConnectorWithPermission({
|
|
|
113
113
|
|
|
114
114
|
export const mcpRouter = createTRPCRouter({
|
|
115
115
|
list: protectedProcedure.query(async ({ ctx }) => {
|
|
116
|
-
if (!config.
|
|
116
|
+
if (!config.ai.tools.mcp.enabled) {
|
|
117
117
|
return [];
|
|
118
118
|
}
|
|
119
119
|
return await getMcpConnectorsByUserId({ userId: ctx.user.id });
|
|
@@ -125,7 +125,7 @@ export const mcpRouter = createTRPCRouter({
|
|
|
125
125
|
* Still includes enabled/disabled state so UI can show toggles.
|
|
126
126
|
*/
|
|
127
127
|
listConnected: protectedProcedure.query(async ({ ctx }) => {
|
|
128
|
-
if (!config.
|
|
128
|
+
if (!config.ai.tools.mcp.enabled) {
|
|
129
129
|
return [];
|
|
130
130
|
}
|
|
131
131
|
const connectors = await getMcpConnectorsByUserId({ userId: ctx.user.id });
|