@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
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
GatewayImageModelIdMap,
|
|
4
4
|
GatewayModelIdMap,
|
|
5
5
|
GatewayType,
|
|
6
|
+
GatewayVideoModelIdMap,
|
|
6
7
|
} from "@/lib/ai/gateways/registry";
|
|
7
8
|
import type { ToolName } from "./ai/types";
|
|
8
9
|
|
|
@@ -12,7 +13,7 @@ const DEFAULT_GATEWAY = "vercel" as const satisfies GatewayType;
|
|
|
12
13
|
const toolName = () => z.custom<ToolName>();
|
|
13
14
|
|
|
14
15
|
// =====================================================
|
|
15
|
-
//
|
|
16
|
+
// AI config — discriminated union keyed on gateway
|
|
16
17
|
// =====================================================
|
|
17
18
|
|
|
18
19
|
function gatewayModelId<G extends GatewayType>() {
|
|
@@ -23,7 +24,37 @@ function gatewayImageModelId<G extends GatewayType>() {
|
|
|
23
24
|
return z.custom<GatewayImageModelIdMap[G]>((v) => typeof v === "string");
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
function
|
|
27
|
+
function gatewayVideoModelId<G extends GatewayType>() {
|
|
28
|
+
return z.custom<GatewayVideoModelIdMap[G]>((v) => typeof v === "string");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const deepResearchToolConfigSchema = z.object({
|
|
32
|
+
defaultModel: z.string(),
|
|
33
|
+
finalReportModel: z.string(),
|
|
34
|
+
allowClarification: z
|
|
35
|
+
.boolean()
|
|
36
|
+
.describe("Whether to ask clarifying questions before starting research"),
|
|
37
|
+
maxResearcherIterations: z
|
|
38
|
+
.number()
|
|
39
|
+
.int()
|
|
40
|
+
.min(1)
|
|
41
|
+
.max(10)
|
|
42
|
+
.describe("Maximum supervisor loop iterations"),
|
|
43
|
+
maxConcurrentResearchUnits: z
|
|
44
|
+
.number()
|
|
45
|
+
.int()
|
|
46
|
+
.min(1)
|
|
47
|
+
.max(20)
|
|
48
|
+
.describe("Topics researched in parallel per iteration"),
|
|
49
|
+
maxSearchQueries: z
|
|
50
|
+
.number()
|
|
51
|
+
.int()
|
|
52
|
+
.min(1)
|
|
53
|
+
.max(10)
|
|
54
|
+
.describe("Max search queries per research topic"),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
function createAiSchema<G extends GatewayType>(g: G) {
|
|
27
58
|
return z.object({
|
|
28
59
|
gateway: z.literal(g),
|
|
29
60
|
providerOrder: z
|
|
@@ -38,39 +69,71 @@ function createModelsSchema<G extends GatewayType>(g: G) {
|
|
|
38
69
|
anonymousModels: z
|
|
39
70
|
.array(gatewayModelId<G>())
|
|
40
71
|
.describe("Models available to anonymous users"),
|
|
41
|
-
|
|
72
|
+
workflows: z
|
|
42
73
|
.object({
|
|
43
74
|
chat: gatewayModelId<G>(),
|
|
44
75
|
title: gatewayModelId<G>(),
|
|
45
76
|
pdf: gatewayModelId<G>(),
|
|
46
|
-
artifact: gatewayModelId<G>(),
|
|
47
|
-
artifactSuggestion: gatewayModelId<G>(),
|
|
48
|
-
followupSuggestions: gatewayModelId<G>(),
|
|
49
|
-
suggestions: gatewayModelId<G>(),
|
|
50
|
-
polishText: gatewayModelId<G>(),
|
|
51
|
-
formatSheet: gatewayModelId<G>(),
|
|
52
|
-
analyzeSheet: gatewayModelId<G>(),
|
|
53
|
-
codeEdits: gatewayModelId<G>(),
|
|
54
77
|
chatImageCompatible: gatewayModelId<G>(),
|
|
55
|
-
image: gatewayImageModelId<G>(),
|
|
56
|
-
deepResearch: gatewayModelId<G>(),
|
|
57
|
-
deepResearchFinalReport: gatewayModelId<G>(),
|
|
58
78
|
})
|
|
59
|
-
.describe("Default model for
|
|
79
|
+
.describe("Default model for shared app workflows"),
|
|
80
|
+
tools: z
|
|
81
|
+
.object({
|
|
82
|
+
webSearch: z.object({
|
|
83
|
+
enabled: z.boolean(),
|
|
84
|
+
}),
|
|
85
|
+
urlRetrieval: z.object({
|
|
86
|
+
enabled: z.boolean(),
|
|
87
|
+
}),
|
|
88
|
+
codeExecution: z.object({
|
|
89
|
+
enabled: z.boolean(),
|
|
90
|
+
}),
|
|
91
|
+
mcp: z.object({
|
|
92
|
+
enabled: z.boolean(),
|
|
93
|
+
}),
|
|
94
|
+
followupSuggestions: z.object({
|
|
95
|
+
enabled: z.boolean(),
|
|
96
|
+
default: gatewayModelId<G>(),
|
|
97
|
+
}),
|
|
98
|
+
text: z.object({
|
|
99
|
+
polish: gatewayModelId<G>(),
|
|
100
|
+
}),
|
|
101
|
+
sheet: z.object({
|
|
102
|
+
format: gatewayModelId<G>(),
|
|
103
|
+
analyze: gatewayModelId<G>(),
|
|
104
|
+
}),
|
|
105
|
+
code: z.object({
|
|
106
|
+
edits: gatewayModelId<G>(),
|
|
107
|
+
}),
|
|
108
|
+
image: z.object({
|
|
109
|
+
enabled: z.boolean(),
|
|
110
|
+
default: gatewayImageModelId<G>(),
|
|
111
|
+
}),
|
|
112
|
+
video: z.object({
|
|
113
|
+
enabled: z.boolean(),
|
|
114
|
+
default: gatewayVideoModelId<G>(),
|
|
115
|
+
}),
|
|
116
|
+
deepResearch: deepResearchToolConfigSchema.extend({
|
|
117
|
+
enabled: z.boolean(),
|
|
118
|
+
defaultModel: gatewayModelId<G>(),
|
|
119
|
+
finalReportModel: gatewayModelId<G>(),
|
|
120
|
+
}),
|
|
121
|
+
})
|
|
122
|
+
.describe("Default model and runtime configuration grouped by tool"),
|
|
60
123
|
});
|
|
61
124
|
}
|
|
62
125
|
|
|
63
126
|
// Record ensures a compile error if a new gateway is added but not here.
|
|
64
127
|
const gatewaySchemaMap: {
|
|
65
|
-
[G in GatewayType]: ReturnType<typeof
|
|
128
|
+
[G in GatewayType]: ReturnType<typeof createAiSchema<G>>;
|
|
66
129
|
} = {
|
|
67
|
-
vercel:
|
|
68
|
-
openrouter:
|
|
69
|
-
openai:
|
|
70
|
-
"openai-compatible":
|
|
130
|
+
vercel: createAiSchema("vercel"),
|
|
131
|
+
openrouter: createAiSchema("openrouter"),
|
|
132
|
+
openai: createAiSchema("openai"),
|
|
133
|
+
"openai-compatible": createAiSchema("openai-compatible"),
|
|
71
134
|
};
|
|
72
135
|
|
|
73
|
-
export const
|
|
136
|
+
export const aiConfigSchema = z
|
|
74
137
|
.discriminatedUnion("gateway", [
|
|
75
138
|
gatewaySchemaMap.vercel,
|
|
76
139
|
gatewaySchemaMap.openrouter,
|
|
@@ -99,22 +162,56 @@ export const modelsConfigSchema = z
|
|
|
99
162
|
"xai/grok-4",
|
|
100
163
|
],
|
|
101
164
|
anonymousModels: ["google/gemini-2.5-flash-lite", "openai/gpt-5-nano"],
|
|
102
|
-
|
|
165
|
+
workflows: {
|
|
103
166
|
chat: "openai/gpt-5-mini",
|
|
104
167
|
title: "openai/gpt-5-nano",
|
|
105
168
|
pdf: "openai/gpt-5-mini",
|
|
106
|
-
artifact: "openai/gpt-5-nano",
|
|
107
|
-
artifactSuggestion: "openai/gpt-5-mini",
|
|
108
|
-
followupSuggestions: "google/gemini-2.5-flash-lite",
|
|
109
|
-
suggestions: "openai/gpt-5-mini",
|
|
110
|
-
polishText: "openai/gpt-5-mini",
|
|
111
|
-
formatSheet: "openai/gpt-5-mini",
|
|
112
|
-
analyzeSheet: "openai/gpt-5-mini",
|
|
113
|
-
codeEdits: "openai/gpt-5-mini",
|
|
114
169
|
chatImageCompatible: "openai/gpt-4o-mini",
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
170
|
+
},
|
|
171
|
+
tools: {
|
|
172
|
+
webSearch: {
|
|
173
|
+
enabled: false,
|
|
174
|
+
},
|
|
175
|
+
urlRetrieval: {
|
|
176
|
+
enabled: false,
|
|
177
|
+
},
|
|
178
|
+
codeExecution: {
|
|
179
|
+
enabled: false,
|
|
180
|
+
},
|
|
181
|
+
mcp: {
|
|
182
|
+
enabled: false,
|
|
183
|
+
},
|
|
184
|
+
followupSuggestions: {
|
|
185
|
+
enabled: false,
|
|
186
|
+
default: "google/gemini-2.5-flash-lite",
|
|
187
|
+
},
|
|
188
|
+
text: {
|
|
189
|
+
polish: "openai/gpt-5-mini",
|
|
190
|
+
},
|
|
191
|
+
sheet: {
|
|
192
|
+
format: "openai/gpt-5-mini",
|
|
193
|
+
analyze: "openai/gpt-5-mini",
|
|
194
|
+
},
|
|
195
|
+
code: {
|
|
196
|
+
edits: "openai/gpt-5-mini",
|
|
197
|
+
},
|
|
198
|
+
image: {
|
|
199
|
+
enabled: false,
|
|
200
|
+
default: "google/gemini-3-pro-image",
|
|
201
|
+
},
|
|
202
|
+
video: {
|
|
203
|
+
enabled: false,
|
|
204
|
+
default: "xai/grok-imagine-video",
|
|
205
|
+
},
|
|
206
|
+
deepResearch: {
|
|
207
|
+
enabled: false,
|
|
208
|
+
defaultModel: "google/gemini-2.5-flash-lite",
|
|
209
|
+
finalReportModel: "google/gemini-3-flash",
|
|
210
|
+
allowClarification: true,
|
|
211
|
+
maxResearcherIterations: 1,
|
|
212
|
+
maxConcurrentResearchUnits: 2,
|
|
213
|
+
maxSearchQueries: 2,
|
|
214
|
+
},
|
|
118
215
|
},
|
|
119
216
|
});
|
|
120
217
|
|
|
@@ -179,67 +276,14 @@ export const attachmentsConfigSchema = z
|
|
|
179
276
|
},
|
|
180
277
|
});
|
|
181
278
|
|
|
182
|
-
export const deepResearchConfigSchema = z
|
|
183
|
-
.object({
|
|
184
|
-
allowClarification: z
|
|
185
|
-
.boolean()
|
|
186
|
-
.describe("Whether to ask clarifying questions before starting research"),
|
|
187
|
-
maxResearcherIterations: z
|
|
188
|
-
.number()
|
|
189
|
-
.int()
|
|
190
|
-
.min(1)
|
|
191
|
-
.max(10)
|
|
192
|
-
.describe("Maximum supervisor loop iterations"),
|
|
193
|
-
maxConcurrentResearchUnits: z
|
|
194
|
-
.number()
|
|
195
|
-
.int()
|
|
196
|
-
.min(1)
|
|
197
|
-
.max(20)
|
|
198
|
-
.describe("Topics researched in parallel per iteration"),
|
|
199
|
-
maxSearchQueries: z
|
|
200
|
-
.number()
|
|
201
|
-
.int()
|
|
202
|
-
.min(1)
|
|
203
|
-
.max(10)
|
|
204
|
-
.describe("Max search queries per research topic"),
|
|
205
|
-
})
|
|
206
|
-
.default({
|
|
207
|
-
allowClarification: true,
|
|
208
|
-
maxResearcherIterations: 1,
|
|
209
|
-
maxConcurrentResearchUnits: 2,
|
|
210
|
-
maxSearchQueries: 2,
|
|
211
|
-
});
|
|
212
|
-
|
|
213
279
|
export const featuresConfigSchema = z
|
|
214
280
|
.object({
|
|
215
|
-
sandbox: z.boolean().describe("Code sandbox execution (Vercel-native)"),
|
|
216
|
-
webSearch: z.boolean().describe("Web search (requires TAVILY_API_KEY)"),
|
|
217
|
-
urlRetrieval: z
|
|
218
|
-
.boolean()
|
|
219
|
-
.describe("URL content retrieval (requires FIRECRAWL_API_KEY)"),
|
|
220
|
-
deepResearch: z
|
|
221
|
-
.boolean()
|
|
222
|
-
.describe("Deep research agent (requires webSearch)"),
|
|
223
|
-
mcp: z.boolean().describe("MCP tool servers (requires MCP_ENCRYPTION_KEY)"),
|
|
224
|
-
imageGeneration: z
|
|
225
|
-
.boolean()
|
|
226
|
-
.describe("AI image generation (requires BLOB_READ_WRITE_TOKEN)"),
|
|
227
281
|
attachments: z
|
|
228
282
|
.boolean()
|
|
229
283
|
.describe("File attachments (requires BLOB_READ_WRITE_TOKEN)"),
|
|
230
|
-
followupSuggestions: z
|
|
231
|
-
.boolean()
|
|
232
|
-
.describe("Follow-up question suggestions after AI responses"),
|
|
233
284
|
})
|
|
234
285
|
.default({
|
|
235
|
-
sandbox: false,
|
|
236
|
-
webSearch: false,
|
|
237
|
-
urlRetrieval: false,
|
|
238
|
-
deepResearch: false,
|
|
239
|
-
mcp: false,
|
|
240
|
-
imageGeneration: false,
|
|
241
286
|
attachments: false,
|
|
242
|
-
followupSuggestions: false,
|
|
243
287
|
});
|
|
244
288
|
|
|
245
289
|
export const authenticationConfigSchema = z
|
|
@@ -334,22 +378,19 @@ export const configSchema = z.object({
|
|
|
334
378
|
|
|
335
379
|
authentication: authenticationConfigSchema,
|
|
336
380
|
|
|
337
|
-
|
|
381
|
+
ai: aiConfigSchema,
|
|
338
382
|
|
|
339
383
|
anonymous: anonymousConfigSchema,
|
|
340
384
|
|
|
341
385
|
attachments: attachmentsConfigSchema,
|
|
342
|
-
|
|
343
|
-
deepResearch: deepResearchConfigSchema,
|
|
344
386
|
});
|
|
345
387
|
|
|
346
388
|
// Output types (after defaults applied)
|
|
347
389
|
export type Config = z.infer<typeof configSchema>;
|
|
348
390
|
export type PricingConfig = z.infer<typeof pricingConfigSchema>;
|
|
349
|
-
export type
|
|
391
|
+
export type AiConfig = z.infer<typeof aiConfigSchema>;
|
|
350
392
|
export type AnonymousConfig = z.infer<typeof anonymousConfigSchema>;
|
|
351
393
|
export type AttachmentsConfig = z.infer<typeof attachmentsConfigSchema>;
|
|
352
|
-
export type DeepResearchConfig = z.infer<typeof deepResearchConfigSchema>;
|
|
353
394
|
export type FeaturesConfig = z.infer<typeof featuresConfigSchema>;
|
|
354
395
|
export type AuthenticationConfig = z.infer<typeof authenticationConfigSchema>;
|
|
355
396
|
|
|
@@ -357,27 +398,72 @@ export type AuthenticationConfig = z.infer<typeof authenticationConfigSchema>;
|
|
|
357
398
|
type ZodConfigInput = z.input<typeof configSchema>;
|
|
358
399
|
|
|
359
400
|
// Use vercel variant as shape reference (all variants share the same structure)
|
|
360
|
-
type
|
|
401
|
+
type AiShape = z.input<typeof gatewaySchemaMap.vercel>;
|
|
402
|
+
type AiToolsShape = AiShape["tools"];
|
|
403
|
+
type DeepResearchToolInputFor<G extends GatewayType> = Omit<
|
|
404
|
+
AiToolsShape["deepResearch"],
|
|
405
|
+
"defaultModel" | "finalReportModel"
|
|
406
|
+
> & {
|
|
407
|
+
defaultModel: GatewayModelIdMap[G];
|
|
408
|
+
finalReportModel: GatewayModelIdMap[G];
|
|
409
|
+
};
|
|
410
|
+
type ImageToolInputFor<G extends GatewayType> = Omit<
|
|
411
|
+
AiToolsShape["image"],
|
|
412
|
+
"default"
|
|
413
|
+
> & {
|
|
414
|
+
default: GatewayImageModelIdMap[G];
|
|
415
|
+
};
|
|
416
|
+
type VideoToolInputFor<G extends GatewayType> = Omit<
|
|
417
|
+
AiToolsShape["video"],
|
|
418
|
+
"default"
|
|
419
|
+
> & {
|
|
420
|
+
default: GatewayVideoModelIdMap[G];
|
|
421
|
+
};
|
|
422
|
+
type FollowupSuggestionsToolInputFor<G extends GatewayType> = Omit<
|
|
423
|
+
AiToolsShape["followupSuggestions"],
|
|
424
|
+
"default"
|
|
425
|
+
> & {
|
|
426
|
+
default: GatewayModelIdMap[G];
|
|
427
|
+
};
|
|
428
|
+
interface AiToolsInputFor<G extends GatewayType> {
|
|
429
|
+
code: {
|
|
430
|
+
[P in keyof AiToolsShape["code"]]: GatewayModelIdMap[G];
|
|
431
|
+
};
|
|
432
|
+
codeExecution: AiToolsShape["codeExecution"];
|
|
433
|
+
deepResearch: DeepResearchToolInputFor<G>;
|
|
434
|
+
followupSuggestions: FollowupSuggestionsToolInputFor<G>;
|
|
435
|
+
image: ImageToolInputFor<G>;
|
|
436
|
+
mcp: AiToolsShape["mcp"];
|
|
437
|
+
sheet: {
|
|
438
|
+
[P in keyof AiToolsShape["sheet"]]: GatewayModelIdMap[G];
|
|
439
|
+
};
|
|
440
|
+
text: {
|
|
441
|
+
[P in keyof AiToolsShape["text"]]: GatewayModelIdMap[G];
|
|
442
|
+
};
|
|
443
|
+
urlRetrieval: AiToolsShape["urlRetrieval"];
|
|
444
|
+
video: VideoToolInputFor<G>;
|
|
445
|
+
webSearch: AiToolsShape["webSearch"];
|
|
446
|
+
}
|
|
361
447
|
|
|
362
|
-
type
|
|
363
|
-
[K in keyof
|
|
448
|
+
type AiInputFor<G extends GatewayType> = {
|
|
449
|
+
[K in keyof AiShape]: K extends "gateway"
|
|
364
450
|
? G
|
|
365
|
-
: K extends "
|
|
451
|
+
: K extends "workflows"
|
|
366
452
|
? {
|
|
367
|
-
[
|
|
368
|
-
? GatewayImageModelIdMap[G]
|
|
369
|
-
: GatewayModelIdMap[G];
|
|
453
|
+
[W in keyof AiShape["workflows"]]: GatewayModelIdMap[G];
|
|
370
454
|
}
|
|
371
|
-
: K extends "
|
|
372
|
-
?
|
|
373
|
-
:
|
|
455
|
+
: K extends "tools"
|
|
456
|
+
? AiToolsInputFor<G>
|
|
457
|
+
: K extends "disabledModels" | "curatedDefaults" | "anonymousModels"
|
|
458
|
+
? GatewayModelIdMap[G][]
|
|
459
|
+
: AiShape[K];
|
|
374
460
|
};
|
|
375
461
|
|
|
376
462
|
type ConfigInputForGateway<G extends GatewayType> = Omit<
|
|
377
463
|
ZodConfigInput,
|
|
378
|
-
"
|
|
464
|
+
"ai"
|
|
379
465
|
> & {
|
|
380
|
-
|
|
466
|
+
ai?: AiInputFor<G>;
|
|
381
467
|
};
|
|
382
468
|
|
|
383
469
|
export type ConfigInput = {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import userConfig from "@/chat.config";
|
|
2
2
|
import type { ActiveGatewayType } from "./ai/app-model-id";
|
|
3
|
-
import { type Config, configSchema
|
|
3
|
+
import { type AiConfig, type Config, configSchema } from "./config-schema";
|
|
4
4
|
|
|
5
|
-
type
|
|
5
|
+
type ActiveAiConfig = Extract<AiConfig, { gateway: ActiveGatewayType }>;
|
|
6
6
|
|
|
7
|
-
/** Config with the `
|
|
8
|
-
type ActiveConfig = Omit<Config, "
|
|
7
|
+
/** Config with the `ai` field narrowed to the active gateway. */
|
|
8
|
+
type ActiveConfig = Omit<Config, "ai"> & { ai: ActiveAiConfig };
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Parsed configuration with defaults applied.
|
|
@@ -2,7 +2,10 @@ import type { AppModelDefinition, AppModelId } from "../ai/app-models";
|
|
|
2
2
|
import { getAppModelDefinition } from "../ai/app-models";
|
|
3
3
|
|
|
4
4
|
/** Minimal usage info needed for cost calculation */
|
|
5
|
-
export
|
|
5
|
+
export interface UsageInfo {
|
|
6
|
+
inputTokens?: number;
|
|
7
|
+
outputTokens?: number;
|
|
8
|
+
}
|
|
6
9
|
|
|
7
10
|
/**
|
|
8
11
|
* Calculate LLM cost in CENTS from AI SDK usage data and model pricing.
|
|
@@ -18,18 +21,18 @@ function calculateLLMCost(
|
|
|
18
21
|
return (inputCost + outputCost) * 100;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
|
|
22
|
-
type: "llm";
|
|
24
|
+
interface LLMCostEntry {
|
|
23
25
|
modelId: AppModelId;
|
|
24
|
-
usage: UsageInfo;
|
|
25
26
|
source: string;
|
|
26
|
-
|
|
27
|
+
type: "llm";
|
|
28
|
+
usage: UsageInfo;
|
|
29
|
+
}
|
|
27
30
|
|
|
28
|
-
|
|
29
|
-
type: "api";
|
|
31
|
+
interface APICostEntry {
|
|
30
32
|
apiName: string;
|
|
31
33
|
cost: number;
|
|
32
|
-
|
|
34
|
+
type: "api";
|
|
35
|
+
}
|
|
33
36
|
|
|
34
37
|
type CostEntry = LLMCostEntry | APICostEntry;
|
|
35
38
|
|
|
@@ -44,7 +44,7 @@ export const serverEnvSchema = {
|
|
|
44
44
|
.optional()
|
|
45
45
|
.describe("Vercel OAuth integration client secret"),
|
|
46
46
|
|
|
47
|
-
// AI Gateway keys (one required depending on config.
|
|
47
|
+
// AI Gateway keys (one required depending on config.ai.gateway)
|
|
48
48
|
AI_GATEWAY_API_KEY: z
|
|
49
49
|
.string()
|
|
50
50
|
.optional()
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { LucideIcon } from "lucide-react";
|
|
2
2
|
import { Brain, Eye, FileText, Image, Mic, Zap } from "lucide-react";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
name: string;
|
|
4
|
+
interface FeatureConfig {
|
|
5
|
+
category: "capability" | "input" | "output";
|
|
7
6
|
description: string;
|
|
8
|
-
icon: LucideIcon;
|
|
9
7
|
enabled: boolean;
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
icon: LucideIcon;
|
|
9
|
+
key: string;
|
|
10
|
+
name: string;
|
|
11
|
+
}
|
|
12
12
|
|
|
13
13
|
export const AVAILABLE_FEATURES: Record<string, FeatureConfig> = {
|
|
14
14
|
reasoning: {
|
|
@@ -14,10 +14,10 @@ import {
|
|
|
14
14
|
findLeafDfsToRightFromMessageId,
|
|
15
15
|
} from "@/lib/thread-utils";
|
|
16
16
|
|
|
17
|
-
export
|
|
18
|
-
siblings: UM[];
|
|
17
|
+
export interface MessageSiblingInfo<UM> {
|
|
19
18
|
siblingIndex: number;
|
|
20
|
-
|
|
19
|
+
siblings: UM[];
|
|
20
|
+
}
|
|
21
21
|
|
|
22
22
|
export type ThreadAugmentedState<UM extends UIMessage> =
|
|
23
23
|
BaseChatStoreState<UM> & {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// Generic message type that works for both DB and anonymous messages
|
|
2
|
-
export
|
|
2
|
+
export interface MessageNode {
|
|
3
3
|
id: string;
|
|
4
4
|
metadata?: {
|
|
5
5
|
parentMessageId: string | null;
|
|
6
6
|
createdAt: Date;
|
|
7
7
|
};
|
|
8
|
-
}
|
|
8
|
+
}
|
|
9
9
|
|
|
10
10
|
/** Safely extract a numeric timestamp from a Date object or ISO string. */
|
|
11
11
|
function toTimestamp(value: Date | string | undefined | null): number {
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import type { ToolName } from "../ai/types";
|
|
2
2
|
import { config } from "../config";
|
|
3
3
|
|
|
4
|
-
export
|
|
4
|
+
export interface AnonymousSession {
|
|
5
|
+
createdAt: Date;
|
|
5
6
|
id: string;
|
|
6
7
|
remainingCredits: number;
|
|
7
|
-
|
|
8
|
-
};
|
|
8
|
+
}
|
|
9
9
|
|
|
10
10
|
const anonConfig = config.anonymous;
|
|
11
11
|
|
|
12
12
|
export const ANONYMOUS_LIMITS = {
|
|
13
13
|
CREDITS: anonConfig.credits,
|
|
14
|
-
AVAILABLE_MODELS: config.
|
|
14
|
+
AVAILABLE_MODELS: config.ai.anonymousModels,
|
|
15
15
|
AVAILABLE_TOOLS: anonConfig.availableTools as ToolName[],
|
|
16
16
|
SESSION_DURATION: 2_147_483_647, // Max session time
|
|
17
17
|
RATE_LIMIT: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export
|
|
2
|
-
id: string;
|
|
1
|
+
export interface UIChat {
|
|
3
2
|
createdAt: Date;
|
|
4
|
-
|
|
5
|
-
title: string;
|
|
6
|
-
visibility: "private" | "public";
|
|
7
|
-
userId: string;
|
|
3
|
+
id: string;
|
|
8
4
|
isPinned: boolean;
|
|
9
5
|
projectId: string | null;
|
|
10
|
-
|
|
6
|
+
title: string;
|
|
7
|
+
updatedAt: Date;
|
|
8
|
+
userId: string;
|
|
9
|
+
visibility: "private" | "public";
|
|
10
|
+
}
|
|
@@ -8,10 +8,10 @@ import type {
|
|
|
8
8
|
|
|
9
9
|
// Minimal utilities to download assets from URL-based parts and inline them.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
mediaType: string | undefined;
|
|
11
|
+
interface DownloadResult {
|
|
13
12
|
data: Uint8Array;
|
|
14
|
-
|
|
13
|
+
mediaType: string | undefined;
|
|
14
|
+
}
|
|
15
15
|
|
|
16
16
|
export type DownloadImplementation = (args: {
|
|
17
17
|
url: URL;
|
|
@@ -2,20 +2,20 @@ import "server-only";
|
|
|
2
2
|
import { config } from "@/lib/config";
|
|
3
3
|
import { ANONYMOUS_LIMITS } from "@/lib/types/anonymous";
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
interface RateLimitResult {
|
|
6
|
+
error?: string;
|
|
7
7
|
remaining: number;
|
|
8
8
|
resetTime: number;
|
|
9
|
-
|
|
10
|
-
}
|
|
9
|
+
success: boolean;
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
interface RateLimitOptions {
|
|
13
13
|
identifier: string;
|
|
14
|
+
keyPrefix: string;
|
|
14
15
|
limit: number;
|
|
15
|
-
windowSize: number;
|
|
16
16
|
redisClient: any;
|
|
17
|
-
|
|
18
|
-
}
|
|
17
|
+
windowSize: number;
|
|
18
|
+
}
|
|
19
19
|
|
|
20
20
|
async function checkRateLimit({
|
|
21
21
|
identifier,
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { NextConfig } from "next";
|
|
2
2
|
|
|
3
|
-
const MODEL_REGISTRY_URL = "airegistry.app";
|
|
4
|
-
|
|
5
3
|
const nextConfig: NextConfig = {
|
|
6
4
|
typedRoutes: true,
|
|
7
5
|
cacheComponents: true,
|
|
8
|
-
|
|
9
6
|
experimental: {
|
|
10
7
|
optimizePackageImports: [
|
|
11
8
|
"react-tweet",
|
|
@@ -36,28 +33,6 @@ const nextConfig: NextConfig = {
|
|
|
36
33
|
},
|
|
37
34
|
],
|
|
38
35
|
},
|
|
39
|
-
redirects: async () => [
|
|
40
|
-
{
|
|
41
|
-
source: "/models",
|
|
42
|
-
destination: `https://${MODEL_REGISTRY_URL}`,
|
|
43
|
-
permanent: true,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
source: "/models/:path*",
|
|
47
|
-
destination: `https://${MODEL_REGISTRY_URL}/models/:path*`,
|
|
48
|
-
permanent: true,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
source: "/compare",
|
|
52
|
-
destination: `https://${MODEL_REGISTRY_URL}/compare`,
|
|
53
|
-
permanent: true,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
source: "/compare/:path*",
|
|
57
|
-
destination: `https://${MODEL_REGISTRY_URL}/compare/:path*`,
|
|
58
|
-
permanent: true,
|
|
59
|
-
},
|
|
60
|
-
],
|
|
61
36
|
};
|
|
62
37
|
|
|
63
38
|
export default nextConfig;
|