@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.
Files changed (160) hide show
  1. package/dist/index.js +394 -247
  2. package/package.json +48 -48
  3. package/templates/chat-app/.claude/skiller.toml +18 -0
  4. package/templates/chat-app/.claude/skills/chat-context/SKILL.md +6 -0
  5. package/templates/chat-app/.claude/skills/chat-context/chat-context.mdc +36 -0
  6. package/templates/chat-app/.claude/skills/lazy-prefetch-pattern/lazy-prefetch-pattern.mdc +27 -0
  7. package/templates/chat-app/.claude/skills/react/react.mdc +29 -0
  8. package/templates/chat-app/.claude/skills/trpc-patterns/trpc-patterns.mdc +77 -0
  9. package/templates/chat-app/.claude/skills/typescript/typescript.mdc +53 -0
  10. package/templates/chat-app/.claude/skills/ultracite/ultracite.mdc +129 -0
  11. package/templates/chat-app/.cursor/skills/chat-context/SKILL.md +37 -0
  12. package/templates/chat-app/.cursor/skills/lazy-prefetch-pattern/SKILL.md +26 -0
  13. package/templates/chat-app/.cursor/skills/react/SKILL.md +28 -0
  14. package/templates/chat-app/.cursor/skills/trpc-patterns/SKILL.md +76 -0
  15. package/templates/chat-app/.cursor/skills/typescript/SKILL.md +52 -0
  16. package/templates/chat-app/.cursor/skills/ultracite/SKILL.md +128 -0
  17. package/templates/chat-app/app/(chat)/actions.ts +17 -13
  18. package/templates/chat-app/app/(chat)/api/chat/[id]/stream/route.ts +6 -5
  19. package/templates/chat-app/app/(chat)/api/chat/route.ts +14 -15
  20. package/templates/chat-app/app/(chat)/chat-providers.tsx +2 -2
  21. package/templates/chat-app/app/(chat)/layout.tsx +7 -6
  22. package/templates/chat-app/app/api/cron/cleanup/route.ts +4 -3
  23. package/templates/chat-app/app/globals.css +23 -23
  24. package/templates/chat-app/app/layout.tsx +1 -1
  25. package/templates/chat-app/biome.jsonc +3 -3
  26. package/templates/chat-app/chat.config.ts +48 -21
  27. package/templates/chat-app/components/anonymous-session-init.tsx +4 -12
  28. package/templates/chat-app/components/artifact-actions.tsx +5 -5
  29. package/templates/chat-app/components/artifact-panel.tsx +6 -6
  30. package/templates/chat-app/components/assistant-message.tsx +1 -1
  31. package/templates/chat-app/components/chat/chat-layout.tsx +2 -2
  32. package/templates/chat-app/components/chat/chat-welcome.tsx +1 -0
  33. package/templates/chat-app/components/chat-features-definitions.ts +11 -8
  34. package/templates/chat-app/components/chat-menu-items.tsx +4 -4
  35. package/templates/chat-app/components/chat-sync.tsx +1 -1
  36. package/templates/chat-app/components/clone-chat-button.tsx +2 -2
  37. package/templates/chat-app/components/code-editor.tsx +5 -5
  38. package/templates/chat-app/components/connectors-dropdown.tsx +2 -2
  39. package/templates/chat-app/components/console.tsx +5 -5
  40. package/templates/chat-app/components/create-artifact.tsx +28 -28
  41. package/templates/chat-app/components/data-stream-provider.tsx +2 -2
  42. package/templates/chat-app/components/deep-research-progress.tsx +2 -2
  43. package/templates/chat-app/components/delete-chat-dialog.tsx +3 -3
  44. package/templates/chat-app/components/delete-project-dialog.tsx +3 -3
  45. package/templates/chat-app/components/diffview.tsx +3 -3
  46. package/templates/chat-app/components/favicon-group.tsx +7 -7
  47. package/templates/chat-app/components/header-breadcrumb.tsx +11 -11
  48. package/templates/chat-app/components/image-editor.tsx +5 -5
  49. package/templates/chat-app/components/image-modal.tsx +4 -4
  50. package/templates/chat-app/components/interactive-chart-impl.tsx +269 -0
  51. package/templates/chat-app/components/interactive-charts.tsx +18 -246
  52. package/templates/chat-app/components/lexical-chat-input.tsx +10 -10
  53. package/templates/chat-app/components/message-editor.tsx +3 -3
  54. package/templates/chat-app/components/message-parts.tsx +8 -3
  55. package/templates/chat-app/components/messages-pane.tsx +4 -4
  56. package/templates/chat-app/components/messages.tsx +5 -5
  57. package/templates/chat-app/components/model-selector.tsx +4 -1
  58. package/templates/chat-app/components/multimodal-input.tsx +14 -5
  59. package/templates/chat-app/components/part/code-execution.tsx +4 -1
  60. package/templates/chat-app/components/part/document-common.tsx +8 -8
  61. package/templates/chat-app/components/part/document-preview.tsx +34 -16
  62. package/templates/chat-app/components/part/document-tool.tsx +3 -3
  63. package/templates/chat-app/components/part/dynamic-tool.tsx +3 -3
  64. package/templates/chat-app/components/part/generate-video.tsx +54 -0
  65. package/templates/chat-app/components/part/message-reasoning.tsx +3 -3
  66. package/templates/chat-app/components/project-details-dialog.tsx +4 -4
  67. package/templates/chat-app/components/project-home.tsx +1 -0
  68. package/templates/chat-app/components/project-icon-picker.tsx +5 -5
  69. package/templates/chat-app/components/project-icon.tsx +4 -4
  70. package/templates/chat-app/components/project-menu-items.tsx +3 -3
  71. package/templates/chat-app/components/research-tasks.tsx +3 -3
  72. package/templates/chat-app/components/sandbox.tsx +4 -4
  73. package/templates/chat-app/components/search-chats-dialog.tsx +11 -11
  74. package/templates/chat-app/components/settings/connectors-settings.tsx +1 -1
  75. package/templates/chat-app/components/settings/settings-nav.tsx +1 -1
  76. package/templates/chat-app/components/sheet-editor.tsx +5 -5
  77. package/templates/chat-app/components/sidebar-chats-list.tsx +5 -5
  78. package/templates/chat-app/components/suggested-actions.tsx +3 -3
  79. package/templates/chat-app/components/text-editor.tsx +5 -5
  80. package/templates/chat-app/components/toolbar.tsx +6 -6
  81. package/templates/chat-app/components/upgrade-cta/login-cta-banner.tsx +5 -5
  82. package/templates/chat-app/components/upgrade-cta/login-prompt.tsx +4 -4
  83. package/templates/chat-app/components/upgrade-cta/share-menu-item.tsx +3 -3
  84. package/templates/chat-app/components/user-message.tsx +3 -3
  85. package/templates/chat-app/components/version-footer.tsx +4 -4
  86. package/templates/chat-app/hooks/chat-sync-hooks.ts +0 -55
  87. package/templates/chat-app/hooks/use-artifact.tsx +3 -3
  88. package/templates/chat-app/hooks/use-auto-focus.ts +37 -7
  89. package/templates/chat-app/hooks/use-media-query.tsx +2 -4
  90. package/templates/chat-app/lib/ai/active-gateway.ts +1 -1
  91. package/templates/chat-app/lib/ai/ai-gateway-models-schemas.ts +30 -6
  92. package/templates/chat-app/lib/ai/app-model-id.ts +1 -1
  93. package/templates/chat-app/lib/ai/app-models.ts +4 -4
  94. package/templates/chat-app/lib/ai/eval-agent.ts +5 -5
  95. package/templates/chat-app/lib/ai/followup-suggestions.ts +5 -2
  96. package/templates/chat-app/lib/ai/gateway-model-defaults.ts +131 -41
  97. package/templates/chat-app/lib/ai/gateways/gateway-provider.ts +10 -6
  98. package/templates/chat-app/lib/ai/gateways/openai-compatible-gateway.ts +9 -4
  99. package/templates/chat-app/lib/ai/gateways/openai-gateway.ts +9 -4
  100. package/templates/chat-app/lib/ai/gateways/openrouter-gateway.ts +17 -12
  101. package/templates/chat-app/lib/ai/gateways/registry.ts +9 -0
  102. package/templates/chat-app/lib/ai/gateways/vercel-gateway.ts +36 -4
  103. package/templates/chat-app/lib/ai/mcp/cache.ts +13 -13
  104. package/templates/chat-app/lib/ai/model-data.ts +21 -20
  105. package/templates/chat-app/lib/ai/models.generated.ts +4397 -3592
  106. package/templates/chat-app/lib/ai/models.ts +1 -1
  107. package/templates/chat-app/lib/ai/providers.ts +10 -0
  108. package/templates/chat-app/lib/ai/text-splitter.ts +3 -4
  109. package/templates/chat-app/lib/ai/to-model-data.ts +1 -0
  110. package/templates/chat-app/lib/ai/tools/code-execution.ts +122 -53
  111. package/templates/chat-app/lib/ai/tools/deep-research/configuration.ts +35 -32
  112. package/templates/chat-app/lib/ai/tools/deep-research/pipeline.ts +2 -2
  113. package/templates/chat-app/lib/ai/tools/deep-research/types.ts +9 -9
  114. package/templates/chat-app/lib/ai/tools/documents/types.ts +4 -4
  115. package/templates/chat-app/lib/ai/tools/generate-image.ts +42 -20
  116. package/templates/chat-app/lib/ai/tools/generate-video.ts +166 -0
  117. package/templates/chat-app/lib/ai/tools/get-weather.ts +20 -20
  118. package/templates/chat-app/lib/ai/tools/read-document.ts +3 -3
  119. package/templates/chat-app/lib/ai/tools/steps/multi-query-web-search.ts +11 -11
  120. package/templates/chat-app/lib/ai/tools/steps/web-search.ts +6 -6
  121. package/templates/chat-app/lib/ai/tools/tools-definitions.ts +10 -5
  122. package/templates/chat-app/lib/ai/tools/tools.ts +15 -6
  123. package/templates/chat-app/lib/ai/tools/types.ts +2 -2
  124. package/templates/chat-app/lib/ai/types.ts +22 -13
  125. package/templates/chat-app/lib/artifacts/code/client.tsx +5 -5
  126. package/templates/chat-app/lib/artifacts/sheet/client.tsx +2 -2
  127. package/templates/chat-app/lib/artifacts/text/client.tsx +18 -3
  128. package/templates/chat-app/lib/clone-messages.test.ts +6 -1
  129. package/templates/chat-app/lib/config-requirements.ts +19 -10
  130. package/templates/chat-app/lib/config-schema.ts +189 -103
  131. package/templates/chat-app/lib/config.ts +4 -4
  132. package/templates/chat-app/lib/credits/cost-accumulator.ts +11 -8
  133. package/templates/chat-app/lib/env-schema.ts +1 -1
  134. package/templates/chat-app/lib/features-config.ts +6 -6
  135. package/templates/chat-app/lib/stores/with-threads.ts +3 -3
  136. package/templates/chat-app/lib/thread-utils.ts +2 -2
  137. package/templates/chat-app/lib/types/anonymous.ts +4 -4
  138. package/templates/chat-app/lib/types/ui-chat.ts +7 -7
  139. package/templates/chat-app/lib/utils/download-assets.ts +3 -3
  140. package/templates/chat-app/lib/utils/rate-limit.ts +8 -8
  141. package/templates/chat-app/next.config.ts +0 -25
  142. package/templates/chat-app/package.json +16 -16
  143. package/templates/chat-app/playwright.config.ts +5 -5
  144. package/templates/chat-app/providers/chat-id-provider.tsx +5 -5
  145. package/templates/chat-app/providers/chat-input-provider.tsx +15 -15
  146. package/templates/chat-app/providers/chat-models-provider.tsx +3 -3
  147. package/templates/chat-app/providers/default-model-provider.tsx +5 -5
  148. package/templates/chat-app/providers/parse-chat-id-from-pathname.test.ts +16 -0
  149. package/templates/chat-app/providers/session-provider.tsx +2 -2
  150. package/templates/chat-app/scripts/check-env.ts +36 -4
  151. package/templates/chat-app/tests/artifacts.e2e.ts +7 -0
  152. package/templates/chat-app/tests/auth.setup.e2e.ts +10 -0
  153. package/templates/chat-app/tests/chat.e2e.ts +7 -0
  154. package/templates/chat-app/tests/reasoning.e2e.ts +7 -0
  155. package/templates/chat-app/tests/reasoning.setup.e2e.ts +10 -0
  156. package/templates/chat-app/trpc/routers/chat.router.ts +1 -1
  157. package/templates/chat-app/trpc/routers/mcp.router.ts +3 -3
  158. package/templates/chat-app/vitest.config.ts +7 -0
  159. package/templates/chat-app/next-env.d.ts +0 -6
  160. 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
- // Models config — discriminated union keyed on gateway
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 createModelsSchema<G extends GatewayType>(g: G) {
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
- defaults: z
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 each task type"),
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 createModelsSchema<G>>;
128
+ [G in GatewayType]: ReturnType<typeof createAiSchema<G>>;
66
129
  } = {
67
- vercel: createModelsSchema("vercel"),
68
- openrouter: createModelsSchema("openrouter"),
69
- openai: createModelsSchema("openai"),
70
- "openai-compatible": createModelsSchema("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 modelsConfigSchema = z
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
- defaults: {
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
- image: "google/gemini-3-pro-image",
116
- deepResearch: "google/gemini-2.5-flash-lite",
117
- deepResearchFinalReport: "google/gemini-3-flash",
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
- models: modelsConfigSchema,
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 ModelsConfig = z.infer<typeof modelsConfigSchema>;
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 ModelsShape = z.input<typeof gatewaySchemaMap.vercel>;
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 ModelsInputFor<G extends GatewayType> = {
363
- [K in keyof ModelsShape]: K extends "gateway"
448
+ type AiInputFor<G extends GatewayType> = {
449
+ [K in keyof AiShape]: K extends "gateway"
364
450
  ? G
365
- : K extends "defaults"
451
+ : K extends "workflows"
366
452
  ? {
367
- [D in keyof ModelsShape["defaults"]]: D extends "image"
368
- ? GatewayImageModelIdMap[G]
369
- : GatewayModelIdMap[G];
453
+ [W in keyof AiShape["workflows"]]: GatewayModelIdMap[G];
370
454
  }
371
- : K extends "disabledModels" | "curatedDefaults" | "anonymousModels"
372
- ? GatewayModelIdMap[G][]
373
- : ModelsShape[K];
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
- "models"
464
+ "ai"
379
465
  > & {
380
- models?: ModelsInputFor<G>;
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, type ModelsConfig } from "./config-schema";
3
+ import { type AiConfig, type Config, configSchema } from "./config-schema";
4
4
 
5
- type ActiveModelsConfig = Extract<ModelsConfig, { gateway: ActiveGatewayType }>;
5
+ type ActiveAiConfig = Extract<AiConfig, { gateway: ActiveGatewayType }>;
6
6
 
7
- /** Config with the `models` field narrowed to the active gateway. */
8
- type ActiveConfig = Omit<Config, "models"> & { models: ActiveModelsConfig };
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 type UsageInfo = { inputTokens?: number; outputTokens?: number };
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
- type LLMCostEntry = {
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
- type APICostEntry = {
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.models.gateway)
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
- type FeatureConfig = {
5
- key: string;
6
- name: string;
4
+ interface FeatureConfig {
5
+ category: "capability" | "input" | "output";
7
6
  description: string;
8
- icon: LucideIcon;
9
7
  enabled: boolean;
10
- category: "capability" | "input" | "output";
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 type MessageSiblingInfo<UM> = {
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 type MessageNode = {
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 type AnonymousSession = {
4
+ export interface AnonymousSession {
5
+ createdAt: Date;
5
6
  id: string;
6
7
  remainingCredits: number;
7
- createdAt: Date;
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.models.anonymousModels,
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 type UIChat = {
2
- id: string;
1
+ export interface UIChat {
3
2
  createdAt: Date;
4
- updatedAt: Date;
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
- type DownloadResult = {
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
- type RateLimitResult = {
6
- success: boolean;
5
+ interface RateLimitResult {
6
+ error?: string;
7
7
  remaining: number;
8
8
  resetTime: number;
9
- error?: string;
10
- };
9
+ success: boolean;
10
+ }
11
11
 
12
- type RateLimitOptions = {
12
+ interface RateLimitOptions {
13
13
  identifier: string;
14
+ keyPrefix: string;
14
15
  limit: number;
15
- windowSize: number;
16
16
  redisClient: any;
17
- keyPrefix: string;
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;