@chat-js/cli 0.1.4 → 0.2.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 +391 -244
- package/package.json +1 -1
- 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 +1 -1
- 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 +22 -22
- package/templates/chat-app/app/layout.tsx +1 -1
- package/templates/chat-app/biome.jsonc +3 -3
- package/templates/chat-app/chat.config.ts +47 -20
- 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 +1 -1
- 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 +15 -15
- 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
|
@@ -8,7 +8,7 @@ import type {
|
|
|
8
8
|
|
|
9
9
|
/** The gateway type actively selected in chat.config.ts */
|
|
10
10
|
export type ActiveGatewayType = typeof chatConfig extends {
|
|
11
|
-
|
|
11
|
+
ai: { gateway: infer G extends GatewayType };
|
|
12
12
|
}
|
|
13
13
|
? G
|
|
14
14
|
: DefaultGateway;
|
|
@@ -15,8 +15,8 @@ export type AppModelDefinition = Omit<ModelData, "id"> & {
|
|
|
15
15
|
apiModelId: ModelId;
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const DISABLED_MODELS = new Set(config.
|
|
19
|
-
const PROVIDER_ORDER = config.
|
|
18
|
+
const DISABLED_MODELS = new Set(config.ai.disabledModels);
|
|
19
|
+
const PROVIDER_ORDER = config.ai.providerOrder;
|
|
20
20
|
|
|
21
21
|
function buildAppModels(models: ModelData[]): AppModelDefinition[] {
|
|
22
22
|
return models
|
|
@@ -116,7 +116,7 @@ export async function getAppModelDefinition(
|
|
|
116
116
|
* so we fall back to an empty set (which auto-enables all models).
|
|
117
117
|
*/
|
|
118
118
|
const KNOWN_MODEL_IDS = new Set<string>(
|
|
119
|
-
generatedForGateway === config.
|
|
119
|
+
generatedForGateway === config.ai.gateway
|
|
120
120
|
? generatedModels.map((m) => m.id)
|
|
121
121
|
: []
|
|
122
122
|
);
|
|
@@ -128,7 +128,7 @@ const KNOWN_MODEL_IDS = new Set<string>(
|
|
|
128
128
|
export function getDefaultEnabledModels(
|
|
129
129
|
appModels: AppModelDefinition[]
|
|
130
130
|
): Set<AppModelId> {
|
|
131
|
-
const enabled = new Set<AppModelId>(config.
|
|
131
|
+
const enabled = new Set<AppModelId>(config.ai.curatedDefaults);
|
|
132
132
|
|
|
133
133
|
// If a curated default has a -reasoning variant, enable it too
|
|
134
134
|
for (const model of appModels) {
|
|
@@ -20,17 +20,17 @@ function createNoOpStreamWriter(): StreamWriter {
|
|
|
20
20
|
} as unknown as StreamWriter;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export
|
|
24
|
-
finalText: string;
|
|
23
|
+
export interface EvalAgentResult {
|
|
25
24
|
assistantMessage: ChatMessage;
|
|
26
|
-
|
|
25
|
+
finalText: string;
|
|
26
|
+
followupSuggestions: string[];
|
|
27
27
|
toolResults: Array<{
|
|
28
28
|
toolName: string;
|
|
29
29
|
type: string;
|
|
30
30
|
state?: string;
|
|
31
31
|
}>;
|
|
32
|
-
|
|
33
|
-
}
|
|
32
|
+
usage: LanguageModelUsage | undefined;
|
|
33
|
+
}
|
|
34
34
|
|
|
35
35
|
async function executeAgentAndGetOutput({
|
|
36
36
|
userMessage,
|
|
@@ -12,7 +12,7 @@ export async function generateFollowupSuggestions(
|
|
|
12
12
|
const minQuestionCount = 3;
|
|
13
13
|
const maxCharactersPerQuestion = 80;
|
|
14
14
|
return streamText({
|
|
15
|
-
model: await getLanguageModel(config.
|
|
15
|
+
model: await getLanguageModel(config.ai.tools.followupSuggestions.default),
|
|
16
16
|
messages: [
|
|
17
17
|
...modelMessages,
|
|
18
18
|
{
|
|
@@ -1,28 +1,58 @@
|
|
|
1
1
|
import type { GatewayType } from "./gateways/registry";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
providerOrder: string[];
|
|
5
|
-
disabledModels: string[];
|
|
6
|
-
curatedDefaults: string[];
|
|
3
|
+
interface ModelDefaults {
|
|
7
4
|
anonymousModels: string[];
|
|
8
|
-
|
|
5
|
+
curatedDefaults: string[];
|
|
6
|
+
disabledModels: string[];
|
|
7
|
+
providerOrder: string[];
|
|
8
|
+
tools: {
|
|
9
|
+
webSearch: {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
};
|
|
12
|
+
urlRetrieval: {
|
|
13
|
+
enabled: boolean;
|
|
14
|
+
};
|
|
15
|
+
codeExecution: {
|
|
16
|
+
enabled: boolean;
|
|
17
|
+
};
|
|
18
|
+
mcp: {
|
|
19
|
+
enabled: boolean;
|
|
20
|
+
};
|
|
21
|
+
followupSuggestions: {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
default: string;
|
|
24
|
+
};
|
|
25
|
+
text: {
|
|
26
|
+
polish: string;
|
|
27
|
+
};
|
|
28
|
+
sheet: {
|
|
29
|
+
format: string;
|
|
30
|
+
analyze: string;
|
|
31
|
+
};
|
|
32
|
+
code: {
|
|
33
|
+
edits: string;
|
|
34
|
+
};
|
|
35
|
+
image: {
|
|
36
|
+
enabled: boolean;
|
|
37
|
+
default: string;
|
|
38
|
+
};
|
|
39
|
+
deepResearch: {
|
|
40
|
+
enabled: boolean;
|
|
41
|
+
defaultModel: string;
|
|
42
|
+
finalReportModel: string;
|
|
43
|
+
allowClarification: boolean;
|
|
44
|
+
maxResearcherIterations: number;
|
|
45
|
+
maxConcurrentResearchUnits: number;
|
|
46
|
+
maxSearchQueries: number;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
workflows: {
|
|
9
50
|
chat: string;
|
|
10
51
|
title: string;
|
|
11
52
|
pdf: string;
|
|
12
|
-
artifact: string;
|
|
13
|
-
artifactSuggestion: string;
|
|
14
|
-
followupSuggestions: string;
|
|
15
|
-
suggestions: string;
|
|
16
|
-
polishText: string;
|
|
17
|
-
formatSheet: string;
|
|
18
|
-
analyzeSheet: string;
|
|
19
|
-
codeEdits: string;
|
|
20
53
|
chatImageCompatible: string;
|
|
21
|
-
image: string;
|
|
22
|
-
deepResearch: string;
|
|
23
|
-
deepResearchFinalReport: string;
|
|
24
54
|
};
|
|
25
|
-
}
|
|
55
|
+
}
|
|
26
56
|
|
|
27
57
|
const multiProviderDefaults = {
|
|
28
58
|
providerOrder: ["openai", "google", "anthropic"],
|
|
@@ -40,22 +70,52 @@ const multiProviderDefaults = {
|
|
|
40
70
|
"xai/grok-4",
|
|
41
71
|
],
|
|
42
72
|
anonymousModels: ["google/gemini-2.5-flash-lite", "openai/gpt-5-nano"],
|
|
43
|
-
|
|
73
|
+
workflows: {
|
|
44
74
|
chat: "openai/gpt-5-mini",
|
|
45
75
|
title: "openai/gpt-5-nano",
|
|
46
76
|
pdf: "openai/gpt-5-mini",
|
|
47
|
-
artifact: "openai/gpt-5-nano",
|
|
48
|
-
artifactSuggestion: "openai/gpt-5-mini",
|
|
49
|
-
followupSuggestions: "google/gemini-2.5-flash-lite",
|
|
50
|
-
suggestions: "openai/gpt-5-mini",
|
|
51
|
-
polishText: "openai/gpt-5-mini",
|
|
52
|
-
formatSheet: "openai/gpt-5-mini",
|
|
53
|
-
analyzeSheet: "openai/gpt-5-mini",
|
|
54
|
-
codeEdits: "openai/gpt-5-mini",
|
|
55
77
|
chatImageCompatible: "openai/gpt-4o-mini",
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
},
|
|
79
|
+
tools: {
|
|
80
|
+
webSearch: {
|
|
81
|
+
enabled: false,
|
|
82
|
+
},
|
|
83
|
+
urlRetrieval: {
|
|
84
|
+
enabled: false,
|
|
85
|
+
},
|
|
86
|
+
codeExecution: {
|
|
87
|
+
enabled: false,
|
|
88
|
+
},
|
|
89
|
+
mcp: {
|
|
90
|
+
enabled: false,
|
|
91
|
+
},
|
|
92
|
+
followupSuggestions: {
|
|
93
|
+
enabled: false,
|
|
94
|
+
default: "google/gemini-2.5-flash-lite",
|
|
95
|
+
},
|
|
96
|
+
text: {
|
|
97
|
+
polish: "openai/gpt-5-mini",
|
|
98
|
+
},
|
|
99
|
+
sheet: {
|
|
100
|
+
format: "openai/gpt-5-mini",
|
|
101
|
+
analyze: "openai/gpt-5-mini",
|
|
102
|
+
},
|
|
103
|
+
code: {
|
|
104
|
+
edits: "openai/gpt-5-mini",
|
|
105
|
+
},
|
|
106
|
+
image: {
|
|
107
|
+
enabled: false,
|
|
108
|
+
default: "google/gemini-3-pro-image",
|
|
109
|
+
},
|
|
110
|
+
deepResearch: {
|
|
111
|
+
enabled: false,
|
|
112
|
+
defaultModel: "google/gemini-2.5-flash-lite",
|
|
113
|
+
finalReportModel: "google/gemini-3-flash",
|
|
114
|
+
allowClarification: true,
|
|
115
|
+
maxResearcherIterations: 1,
|
|
116
|
+
maxConcurrentResearchUnits: 2,
|
|
117
|
+
maxSearchQueries: 2,
|
|
118
|
+
},
|
|
59
119
|
},
|
|
60
120
|
} satisfies ModelDefaults;
|
|
61
121
|
|
|
@@ -69,22 +129,52 @@ const openaiOnlyDefaults = {
|
|
|
69
129
|
"gpt-5.2-chat-latest",
|
|
70
130
|
],
|
|
71
131
|
anonymousModels: ["gpt-5-nano"],
|
|
72
|
-
|
|
132
|
+
workflows: {
|
|
73
133
|
chat: "gpt-5-mini",
|
|
74
134
|
title: "gpt-5-nano",
|
|
75
135
|
pdf: "gpt-5-mini",
|
|
76
|
-
artifact: "gpt-5-nano",
|
|
77
|
-
artifactSuggestion: "gpt-5-mini",
|
|
78
|
-
followupSuggestions: "gpt-5-nano",
|
|
79
|
-
suggestions: "gpt-5-mini",
|
|
80
|
-
polishText: "gpt-5-mini",
|
|
81
|
-
formatSheet: "gpt-5-mini",
|
|
82
|
-
analyzeSheet: "gpt-5-mini",
|
|
83
|
-
codeEdits: "gpt-5-mini",
|
|
84
136
|
chatImageCompatible: "gpt-4o-mini",
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
137
|
+
},
|
|
138
|
+
tools: {
|
|
139
|
+
webSearch: {
|
|
140
|
+
enabled: false,
|
|
141
|
+
},
|
|
142
|
+
urlRetrieval: {
|
|
143
|
+
enabled: false,
|
|
144
|
+
},
|
|
145
|
+
codeExecution: {
|
|
146
|
+
enabled: false,
|
|
147
|
+
},
|
|
148
|
+
mcp: {
|
|
149
|
+
enabled: false,
|
|
150
|
+
},
|
|
151
|
+
followupSuggestions: {
|
|
152
|
+
enabled: false,
|
|
153
|
+
default: "gpt-5-nano",
|
|
154
|
+
},
|
|
155
|
+
text: {
|
|
156
|
+
polish: "gpt-5-mini",
|
|
157
|
+
},
|
|
158
|
+
sheet: {
|
|
159
|
+
format: "gpt-5-mini",
|
|
160
|
+
analyze: "gpt-5-mini",
|
|
161
|
+
},
|
|
162
|
+
code: {
|
|
163
|
+
edits: "gpt-5-mini",
|
|
164
|
+
},
|
|
165
|
+
image: {
|
|
166
|
+
enabled: false,
|
|
167
|
+
default: "gpt-image-1",
|
|
168
|
+
},
|
|
169
|
+
deepResearch: {
|
|
170
|
+
enabled: false,
|
|
171
|
+
defaultModel: "gpt-5-nano",
|
|
172
|
+
finalReportModel: "gpt-5-mini",
|
|
173
|
+
allowClarification: true,
|
|
174
|
+
maxResearcherIterations: 1,
|
|
175
|
+
maxConcurrentResearchUnits: 2,
|
|
176
|
+
maxSearchQueries: 2,
|
|
177
|
+
},
|
|
88
178
|
},
|
|
89
179
|
} satisfies ModelDefaults;
|
|
90
180
|
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
+
import type { Experimental_VideoModelV3 } from "@ai-sdk/provider";
|
|
1
2
|
import type { ImageModel, LanguageModel } from "ai";
|
|
2
3
|
import type { AiGatewayModel } from "../ai-gateway-models-schemas";
|
|
3
4
|
|
|
4
|
-
export
|
|
5
|
+
export interface GatewayProvider<
|
|
5
6
|
TGateway extends string = string,
|
|
6
7
|
TModelId extends string = string,
|
|
7
8
|
TImageModelId extends string = string,
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
TVideoModelId extends string = string,
|
|
10
|
+
> {
|
|
11
|
+
/** Create a dedicated image model instance, or null if unsupported */
|
|
12
|
+
createImageModel(modelId: TImageModelId): ImageModel | null;
|
|
10
13
|
|
|
11
14
|
/** Create a language model instance from a model ID like "openai/gpt-5-nano" */
|
|
12
15
|
createLanguageModel(modelId: TModelId): LanguageModel;
|
|
13
16
|
|
|
14
|
-
/** Create a
|
|
15
|
-
|
|
17
|
+
/** Create a video model instance, or null if unsupported */
|
|
18
|
+
createVideoModel(modelId: TVideoModelId): Experimental_VideoModelV3 | null;
|
|
16
19
|
|
|
17
20
|
/** Fetch the list of available models from the gateway's API */
|
|
18
21
|
fetchModels(): Promise<AiGatewayModel[]>;
|
|
19
|
-
|
|
22
|
+
readonly type: TGateway;
|
|
23
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
2
|
+
import type { Experimental_VideoModelV3 } from "@ai-sdk/provider";
|
|
2
3
|
import type { ImageModel, LanguageModel } from "ai";
|
|
3
4
|
import { createModuleLogger } from "@/lib/logger";
|
|
4
5
|
import type { AiGatewayModel } from "../ai-gateway-models-schemas";
|
|
@@ -7,12 +8,12 @@ import type { GatewayProvider } from "./gateway-provider";
|
|
|
7
8
|
|
|
8
9
|
const log = createModuleLogger("ai/gateways/openai-compatible");
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
interface OpenAICompatibleModelResponse {
|
|
12
|
+
created: number;
|
|
11
13
|
id: string;
|
|
12
14
|
object: string;
|
|
13
|
-
created: number;
|
|
14
15
|
owned_by: string;
|
|
15
|
-
}
|
|
16
|
+
}
|
|
16
17
|
|
|
17
18
|
function toAiGatewayModel(
|
|
18
19
|
model: OpenAICompatibleModelResponse
|
|
@@ -32,7 +33,7 @@ function toAiGatewayModel(
|
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
export class OpenAICompatibleGateway
|
|
35
|
-
implements GatewayProvider<"openai-compatible", string, string>
|
|
36
|
+
implements GatewayProvider<"openai-compatible", string, string, never>
|
|
36
37
|
{
|
|
37
38
|
readonly type = "openai-compatible" as const;
|
|
38
39
|
|
|
@@ -59,6 +60,10 @@ export class OpenAICompatibleGateway
|
|
|
59
60
|
return provider.imageModel(modelId);
|
|
60
61
|
}
|
|
61
62
|
|
|
63
|
+
createVideoModel(_modelId: never): Experimental_VideoModelV3 | null {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
62
67
|
private getApiKey(): string | undefined {
|
|
63
68
|
return process.env.OPENAI_COMPATIBLE_API_KEY;
|
|
64
69
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createOpenAI } from "@ai-sdk/openai";
|
|
2
|
+
import type { Experimental_VideoModelV3 } from "@ai-sdk/provider";
|
|
2
3
|
import type { ImageModel, LanguageModel } from "ai";
|
|
3
4
|
import { env } from "@/lib/env";
|
|
4
5
|
import { createModuleLogger } from "@/lib/logger";
|
|
@@ -20,12 +21,12 @@ type OpenaiImageModelId = StrictLiterals<
|
|
|
20
21
|
ExtractImageModelIdFromProvider<typeof createOpenAI>
|
|
21
22
|
>;
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
interface OpenAIModelResponse {
|
|
25
|
+
created: number;
|
|
24
26
|
id: string;
|
|
25
27
|
object: string;
|
|
26
|
-
created: number;
|
|
27
28
|
owned_by: string;
|
|
28
|
-
}
|
|
29
|
+
}
|
|
29
30
|
|
|
30
31
|
function toAiGatewayModel(model: OpenAIModelResponse): AiGatewayModel {
|
|
31
32
|
return {
|
|
@@ -45,7 +46,7 @@ function toAiGatewayModel(model: OpenAIModelResponse): AiGatewayModel {
|
|
|
45
46
|
|
|
46
47
|
export class OpenAIGateway
|
|
47
48
|
implements
|
|
48
|
-
GatewayProvider<"openai", OpenaiLanguageModelId, OpenaiImageModelId>
|
|
49
|
+
GatewayProvider<"openai", OpenaiLanguageModelId, OpenaiImageModelId, never>
|
|
49
50
|
{
|
|
50
51
|
readonly type = "openai" as const;
|
|
51
52
|
|
|
@@ -67,6 +68,10 @@ export class OpenAIGateway
|
|
|
67
68
|
return provider.image(modelId);
|
|
68
69
|
}
|
|
69
70
|
|
|
71
|
+
createVideoModel(_modelId: never): Experimental_VideoModelV3 | null {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
70
75
|
private getApiKey(): string | undefined {
|
|
71
76
|
return env.OPENAI_API_KEY;
|
|
72
77
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Experimental_VideoModelV3 } from "@ai-sdk/provider";
|
|
1
2
|
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
|
|
2
3
|
import type { ImageModel, LanguageModel } from "ai";
|
|
3
4
|
import { createModuleLogger } from "@/lib/logger";
|
|
@@ -7,21 +8,17 @@ import type { GatewayProvider } from "./gateway-provider";
|
|
|
7
8
|
|
|
8
9
|
const log = createModuleLogger("ai/gateways/openrouter");
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
id: string;
|
|
12
|
-
name: string;
|
|
13
|
-
created: number;
|
|
14
|
-
description: string;
|
|
15
|
-
context_length: number | null;
|
|
11
|
+
interface OpenRouterModelResponse {
|
|
16
12
|
architecture: {
|
|
17
13
|
modality?: string;
|
|
18
14
|
input_modalities?: string[];
|
|
19
15
|
output_modalities?: string[];
|
|
20
16
|
} | null;
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
17
|
+
context_length: number | null;
|
|
18
|
+
created: number;
|
|
19
|
+
description: string;
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
25
22
|
pricing: {
|
|
26
23
|
prompt?: string;
|
|
27
24
|
completion?: string;
|
|
@@ -32,7 +29,11 @@ type OpenRouterModelResponse = {
|
|
|
32
29
|
input_cache_write?: string;
|
|
33
30
|
} | null;
|
|
34
31
|
supported_parameters?: string[] | null;
|
|
35
|
-
|
|
32
|
+
top_provider: {
|
|
33
|
+
context_length?: number | null;
|
|
34
|
+
max_completion_tokens: number | null;
|
|
35
|
+
} | null;
|
|
36
|
+
}
|
|
36
37
|
|
|
37
38
|
function deriveTags(model: OpenRouterModelResponse): string[] {
|
|
38
39
|
const inputMods = model.architecture?.input_modalities ?? ["text"];
|
|
@@ -95,7 +96,7 @@ function toAiGatewayModel(model: OpenRouterModelResponse): AiGatewayModel {
|
|
|
95
96
|
}
|
|
96
97
|
|
|
97
98
|
export class OpenRouterGateway
|
|
98
|
-
implements GatewayProvider<"openrouter", string, string>
|
|
99
|
+
implements GatewayProvider<"openrouter", string, string, never>
|
|
99
100
|
{
|
|
100
101
|
readonly type = "openrouter" as const;
|
|
101
102
|
|
|
@@ -118,6 +119,10 @@ export class OpenRouterGateway
|
|
|
118
119
|
return null;
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
createVideoModel(_modelId: never): Experimental_VideoModelV3 | null {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
|
|
121
126
|
private getApiKey(): string | undefined {
|
|
122
127
|
return process.env.OPENROUTER_API_KEY;
|
|
123
128
|
}
|
|
@@ -60,3 +60,12 @@ export type GatewayImageModelIdMap = {
|
|
|
60
60
|
| InferImageModelId<K>
|
|
61
61
|
| (K extends typeof generatedForGateway ? MultimodalImageModel : never);
|
|
62
62
|
};
|
|
63
|
+
|
|
64
|
+
/** Infer video model ID type from a gateway's `createVideoModel` parameter */
|
|
65
|
+
type InferVideoModelId<T extends GatewayType> = Parameters<
|
|
66
|
+
ReturnType<(typeof gatewayRegistry)[T]>["createVideoModel"]
|
|
67
|
+
>[0];
|
|
68
|
+
|
|
69
|
+
export type GatewayVideoModelIdMap = {
|
|
70
|
+
[K in GatewayType]: InferVideoModelId<K>;
|
|
71
|
+
};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { gateway } from "@ai-sdk/gateway";
|
|
2
|
+
import type { Experimental_VideoModelV3 } from "@ai-sdk/provider";
|
|
2
3
|
import type { ImageModel, LanguageModel } from "ai";
|
|
3
4
|
import { createModuleLogger } from "@/lib/logger";
|
|
4
5
|
import {
|
|
5
6
|
type AiGatewayModel,
|
|
6
7
|
aiGatewayModelsResponseSchema,
|
|
8
|
+
isAiGatewayModelType,
|
|
7
9
|
} from "../ai-gateway-models-schemas";
|
|
8
10
|
import { getFallbackModels } from "./fallback-models";
|
|
9
11
|
import type { GatewayProvider } from "./gateway-provider";
|
|
@@ -12,13 +14,19 @@ import type { StrictLiterals } from "./provider-types";
|
|
|
12
14
|
const log = createModuleLogger("ai/gateways/vercel");
|
|
13
15
|
|
|
14
16
|
type VercelImageModelId = Parameters<(typeof gateway)["imageModel"]>[0];
|
|
17
|
+
type VercelVideoModelId = Parameters<(typeof gateway)["videoModel"]>[0];
|
|
15
18
|
type VercelLanguageModelId = StrictLiterals<
|
|
16
19
|
Parameters<(typeof gateway)["languageModel"]>[0]
|
|
17
20
|
>;
|
|
18
21
|
|
|
19
22
|
export class VercelGateway
|
|
20
23
|
implements
|
|
21
|
-
GatewayProvider<
|
|
24
|
+
GatewayProvider<
|
|
25
|
+
"vercel",
|
|
26
|
+
VercelLanguageModelId,
|
|
27
|
+
VercelImageModelId,
|
|
28
|
+
VercelVideoModelId
|
|
29
|
+
>
|
|
22
30
|
{
|
|
23
31
|
readonly type = "vercel" as const;
|
|
24
32
|
|
|
@@ -30,6 +38,10 @@ export class VercelGateway
|
|
|
30
38
|
return gateway.imageModel(modelId);
|
|
31
39
|
}
|
|
32
40
|
|
|
41
|
+
createVideoModel(modelId: VercelVideoModelId): Experimental_VideoModelV3 {
|
|
42
|
+
return gateway.videoModel(modelId);
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
private getApiKey(): string | undefined {
|
|
34
46
|
return process.env.AI_GATEWAY_API_KEY || process.env.VERCEL_OIDC_TOKEN;
|
|
35
47
|
}
|
|
@@ -68,13 +80,33 @@ export class VercelGateway
|
|
|
68
80
|
|
|
69
81
|
const bodyRaw = await response.json();
|
|
70
82
|
const body = aiGatewayModelsResponseSchema.parse(bodyRaw);
|
|
71
|
-
const
|
|
83
|
+
const unsupportedTypes = new Set<string>();
|
|
84
|
+
const models: AiGatewayModel[] = [];
|
|
85
|
+
|
|
86
|
+
for (const model of body.data) {
|
|
87
|
+
if (!isAiGatewayModelType(model.type)) {
|
|
88
|
+
unsupportedTypes.add(model.type);
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
models.push({ ...model, type: model.type });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (unsupportedTypes.size > 0) {
|
|
95
|
+
log.warn(
|
|
96
|
+
{
|
|
97
|
+
unsupportedTypes: [...unsupportedTypes],
|
|
98
|
+
skippedModelCount: body.data.length - models.length,
|
|
99
|
+
modelCount: body.data.length,
|
|
100
|
+
},
|
|
101
|
+
"Skipping models with unsupported types from Vercel AI Gateway"
|
|
102
|
+
);
|
|
103
|
+
}
|
|
72
104
|
|
|
73
105
|
log.info(
|
|
74
|
-
{ modelCount },
|
|
106
|
+
{ modelCount: models.length },
|
|
75
107
|
"Successfully fetched models from Vercel AI Gateway"
|
|
76
108
|
);
|
|
77
|
-
return
|
|
109
|
+
return models;
|
|
78
110
|
} catch (error) {
|
|
79
111
|
log.error(
|
|
80
112
|
{ err: error, url },
|
|
@@ -11,25 +11,18 @@ const mcpCacheTags = {
|
|
|
11
11
|
} as const;
|
|
12
12
|
|
|
13
13
|
// Types for cached results
|
|
14
|
-
export
|
|
14
|
+
export interface ConnectionStatusResult {
|
|
15
|
+
error?: string;
|
|
16
|
+
needsAuth: boolean;
|
|
15
17
|
status:
|
|
16
18
|
| "disconnected"
|
|
17
19
|
| "connecting"
|
|
18
20
|
| "connected"
|
|
19
21
|
| "authorizing"
|
|
20
22
|
| "incompatible";
|
|
21
|
-
|
|
22
|
-
error?: string;
|
|
23
|
-
};
|
|
23
|
+
}
|
|
24
24
|
|
|
25
|
-
export
|
|
26
|
-
tools: Array<{ name: string; description: string | null }>;
|
|
27
|
-
resources: Array<{
|
|
28
|
-
name: string;
|
|
29
|
-
uri: string;
|
|
30
|
-
description: string | null;
|
|
31
|
-
mimeType: string | null;
|
|
32
|
-
}>;
|
|
25
|
+
export interface DiscoveryResult {
|
|
33
26
|
prompts: Array<{
|
|
34
27
|
name: string;
|
|
35
28
|
description: string | null;
|
|
@@ -39,7 +32,14 @@ export type DiscoveryResult = {
|
|
|
39
32
|
required: boolean;
|
|
40
33
|
}>;
|
|
41
34
|
}>;
|
|
42
|
-
|
|
35
|
+
resources: Array<{
|
|
36
|
+
name: string;
|
|
37
|
+
uri: string;
|
|
38
|
+
description: string | null;
|
|
39
|
+
mimeType: string | null;
|
|
40
|
+
}>;
|
|
41
|
+
tools: Array<{ name: string; description: string | null }>;
|
|
42
|
+
}
|
|
43
43
|
|
|
44
44
|
/**
|
|
45
45
|
* Create a cached connection status fetcher for a specific connector.
|
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
id: string;
|
|
3
|
-
object: string;
|
|
4
|
-
owned_by: string;
|
|
5
|
-
name: string;
|
|
6
|
-
description: string;
|
|
7
|
-
type: "language" | "embedding" | "image";
|
|
8
|
-
tags?: string[];
|
|
1
|
+
export interface ModelData {
|
|
9
2
|
context_window: number;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
input?: string;
|
|
13
|
-
output?: string;
|
|
14
|
-
input_cache_read?: string;
|
|
15
|
-
input_cache_write?: string;
|
|
16
|
-
web_search?: string;
|
|
17
|
-
image?: string;
|
|
18
|
-
};
|
|
19
|
-
reasoning: boolean;
|
|
20
|
-
toolCall: boolean;
|
|
3
|
+
description: string;
|
|
4
|
+
id: string;
|
|
21
5
|
input: {
|
|
22
6
|
image: boolean;
|
|
23
7
|
text: boolean;
|
|
@@ -25,9 +9,26 @@ export type ModelData = {
|
|
|
25
9
|
video: boolean;
|
|
26
10
|
audio: boolean;
|
|
27
11
|
};
|
|
12
|
+
max_tokens: number;
|
|
13
|
+
name: string;
|
|
14
|
+
object: string;
|
|
28
15
|
output: {
|
|
29
16
|
image: boolean;
|
|
30
17
|
text: boolean;
|
|
31
18
|
audio: boolean;
|
|
19
|
+
video: boolean;
|
|
32
20
|
};
|
|
33
|
-
|
|
21
|
+
owned_by: string;
|
|
22
|
+
pricing: {
|
|
23
|
+
input?: string;
|
|
24
|
+
output?: string;
|
|
25
|
+
input_cache_read?: string;
|
|
26
|
+
input_cache_write?: string;
|
|
27
|
+
web_search?: string;
|
|
28
|
+
image?: string;
|
|
29
|
+
};
|
|
30
|
+
reasoning: boolean;
|
|
31
|
+
tags?: string[];
|
|
32
|
+
toolCall: boolean;
|
|
33
|
+
type: "language" | "embedding" | "image" | "video";
|
|
34
|
+
}
|