Skip to content

Commit 0a36b85

Browse files
committed
Bump ai sdk
1 parent c7a52cc commit 0a36b85

9 files changed

Lines changed: 280 additions & 951 deletions

File tree

dependency-upgrades.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Dependency Upgrades
2+
3+
Last updated: 2026-04-06
4+
5+
## Current Status
6+
7+
- Done this session:
8+
- AI SDK migration landed
9+
- workspace `zod` bumped from `3.23.8` to `3.25.76`
10+
- `ai` and `@ai-sdk/*` packages aligned to current major versions
11+
- OpenAI-compatible providers switched to explicit `.chat(...)` calls for `baseURL` compatibility
12+
- Verification completed:
13+
- `corepack pnpm install`
14+
- `corepack pnpm --filter @srcbook/shared check-types`
15+
- `corepack pnpm --filter @srcbook/api check-types`
16+
- `corepack pnpm --filter @srcbook/web check-types`
17+
- `corepack pnpm --filter @srcbook/api build`
18+
- `corepack pnpm --filter srcbook build`
19+
- `corepack pnpm --filter @srcbook/api test -- --run`
20+
- Remaining validation:
21+
- live AI provider smoke tests with real credentials
22+
23+
## Baseline
24+
25+
- Pre-upgrade targeted typechecks passed:
26+
- `corepack pnpm --filter @srcbook/shared check-types`
27+
- `corepack pnpm --filter @srcbook/api check-types`
28+
- `corepack pnpm --filter @srcbook/web check-types`
29+
- Current AI SDK usage is server-side and narrowly scoped to:
30+
- `packages/api/ai/config.mts`
31+
- `packages/api/ai/generate.mts`
32+
33+
## Recommended Sequence
34+
35+
1. Easy sweep: same-major patch/minor bumps with low API-change risk.
36+
2. AI SDK stack: `ai` + `@ai-sdk/*` alignment, with a minimum `zod` bump first.
37+
3. Tooling majors: Vite, Vitest, vite-node, TypeScript, ESLint stack.
38+
4. Runtime/framework majors: React 19, React Router 7, Tailwind 4.
39+
5. Backend/runtime majors: Express 5, Drizzle, `better-sqlite3`, `marked`, PostHog.
40+
41+
## Easy Bumps
42+
43+
These look like the obvious low-risk batch. They are mostly same-major upgrades, often patch/minor-only, and do not appear to require architectural changes.
44+
45+
- Root/tooling:
46+
- `@changesets/cli` `2.27.8 -> 2.30.0`
47+
- `prettier` `3.3.3 -> 3.8.1`
48+
- `turbo` `2.1.1 -> 2.9.4`
49+
- Catalog/shared:
50+
- `ws` `8.18.0 -> 8.20.0`
51+
- `zod` `3.23.8 -> 3.25.76+` as a likely prerequisite for AI SDK
52+
- API:
53+
- `cors` `2.8.5 -> 2.8.6`
54+
- `@types/better-sqlite3` `7.6.11 -> 7.6.13`
55+
- `@types/cors` `2.8.17 -> 2.8.19`
56+
- `@types/ws` `8.5.12 -> 8.18.1`
57+
- Web/components leaf deps:
58+
- `autoprefixer` `10.4.20 -> 10.4.27`
59+
- `postcss` `8.4.45 -> 8.5.8`
60+
- `react-textarea-autosize` `8.5.3 -> 8.5.9`
61+
- `use-debounce` `10.0.3 -> 10.1.1`
62+
- `class-variance-authority` `0.7.0 -> 0.7.1`
63+
- `cmdk` `1.0.0 -> 1.1.1`
64+
- `mermaid` `11.2.0 -> 11.14.0`
65+
- `chalk` `5.3.0 -> 5.6.2`
66+
- Editor/UI same-major bumps:
67+
- `@codemirror/*` currently have several patch/minor bumps only
68+
- `@radix-ui/*` currently have several same-major minor bumps only
69+
- `@uiw/*` currently have same-major minor bumps only
70+
71+
## Medium-Risk Upgrades
72+
73+
- AI SDK stack:
74+
- `ai` `3.4.33 / 3.3.33 -> 6.0.149`
75+
- `@ai-sdk/openai` `0.0.58 -> 3.0.51`
76+
- `@ai-sdk/anthropic` `0.0.49 -> 3.0.67`
77+
- `@ai-sdk/google` `1.0.3 -> 3.0.59`
78+
- `@ai-sdk/provider` `1.0.1 -> 3.0.8`
79+
- Type/tooling:
80+
- `typescript` `5.6.2 -> 6.0.2`
81+
- `@types/node` `20.14.2 / 22.5.4 -> 25.5.2`
82+
- `eslint` `8.57.0 -> 10.2.0`
83+
- `@typescript-eslint/*` `8.5.0 -> 8.58.0`
84+
- Data/runtime:
85+
- `drizzle-kit` `0.24.2 -> 0.31.10`
86+
- `drizzle-orm` `0.33.0 -> 0.45.2`
87+
- `posthog-node` `4.2.0 -> 5.28.11`
88+
- `posthog-js` `1.174.2 -> 1.364.7`
89+
90+
## Likely Gnarly
91+
92+
- React stack:
93+
- `react` `18.3.1 -> 19.2.4`
94+
- `react-dom` `18.3.1 -> 19.2.4`
95+
- `@types/react` `18.3.5 -> 19.2.14`
96+
- `@types/react-dom` `18.3.0 -> 19.2.3`
97+
- `react-router-dom` `6.26.2 -> 7.14.0`
98+
- CSS/build:
99+
- `tailwindcss` `3.4.11 -> 4.2.2`
100+
- `tailwind-merge` `2.5.2 -> 3.5.0`
101+
- `@vitejs/plugin-react-swc` `3.7.0 -> 4.3.0`
102+
- `vite` `5.4.4 -> 8.0.5`
103+
- `vite-node` `2.0.5 -> 6.0.0`
104+
- `vitest` `2.0.5 -> 4.1.2`
105+
- Backend/runtime:
106+
- `express` `4.20.0 -> 5.2.1`
107+
- `better-sqlite3` `11.3.0 -> 12.8.0`
108+
- `marked` `14.1.2 -> 17.0.6`
109+
- `marked-react` `2.0.0 -> 4.0.0`
110+
- `zod` `3.x -> 4.x` as a separate workspace-wide migration if we choose that path later
111+
112+
## AI SDK Focus
113+
114+
Status: compile/build/test migration completed on 2026-04-06. Live credential-backed smoke testing is still pending.
115+
116+
Important constraints:
117+
118+
- The repo currently uses:
119+
- `createOpenAI`
120+
- `createAnthropic`
121+
- `createGoogleGenerativeAI`
122+
- `generateText`
123+
- The repo does not currently use:
124+
- `streamText`
125+
- `streamObject`
126+
- AI SDK UI hooks/components
127+
- tool-calling flows in local code
128+
- The current OpenAI provider docs still support `createOpenAI({ baseURL })`.
129+
- Since AI SDK 5, the OpenAI provider uses the Responses API by default. If behavior shifts for specific models, we may need to explicitly choose `.chat(...)` for compatibility.
130+
- Official docs recommend `zod 4.1.8+` for AI SDK 5+, but current npm peer deps for `ai@6.0.149` allow `zod ^3.25.76 || ^4.1.8`.
131+
- In practice for this repo, explicit `.chat(...)` calls are now used for OpenAI-compatible `baseURL` providers to avoid accidental Responses API routing for OpenRouter, xAI, and custom endpoints.
132+
133+
Recommended upgrade strategy for AI SDK:
134+
135+
1. Done: bump workspace `zod` from `3.23.8` to latest `3.25.x`.
136+
2. Done: align all AI SDK packages together.
137+
3. Done: run targeted typechecks for `@srcbook/shared`, `@srcbook/api`, and `@srcbook/web`.
138+
4. Pending: smoke-test AI provider selection paths:
139+
- OpenAI strict
140+
- Anthropic
141+
- Gemini
142+
- OpenRouter / xAI / custom `baseURL`
143+
5. Done for compatibility endpoints: explicit `.chat(...)` selection is already in place where needed.
144+
145+
## References
146+
147+
- AI SDK 3.4 -> 4.0 migration guide: https://ai-sdk.dev/docs/migration-guides/migration-guide-4-0
148+
- AI SDK 4.x -> 5.0 migration guide: https://ai-sdk.dev/docs/migration-guides/migration-guide-5-0
149+
- AI SDK 5.x -> 6.0 migration guide: https://ai-sdk.dev/docs/migration-guides/migration-guide-6-0
150+
- Current OpenAI provider docs: https://ai-sdk.dev/providers/ai-sdk-providers/openai
151+
152+
## Next Suggested Work
153+
154+
- Optional quick win:
155+
- land a same-major easy-bumps batch first
156+
- Strong candidate after that:
157+
- same-major easy-bumps batch
158+
- AI-specific follow-up:
159+
- credential-backed smoke tests for each configured provider path
160+
- Explicitly avoid starting with:
161+
- React 19
162+
- Tailwind 4
163+
- Express 5

packages/api/ai/config.mts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@ export async function getModel(): Promise<LanguageModel> {
1919
throw new Error('OpenAI API key is not set');
2020
}
2121
const openai = createOpenAI({
22-
compatibility: 'strict', // strict mode, enabled when using the OpenAI API
2322
apiKey: config.openaiKey,
2423
});
25-
return openai(model);
24+
return openai.chat(model);
2625

2726
case 'anthropic':
2827
if (!config.anthropicKey) {
@@ -43,32 +42,29 @@ export async function getModel(): Promise<LanguageModel> {
4342
throw new Error('Xai API key is not set');
4443
}
4544
const xai = createOpenAI({
46-
compatibility: 'compatible',
4745
baseURL: 'https://api.x.ai/v1',
4846
apiKey: config.xaiKey,
4947
});
50-
return xai(model);
48+
return xai.chat(model);
5149

5250
case 'openrouter':
5351
if (!config.openrouterKey) {
5452
throw new Error('OpenRouter API key is not set');
5553
}
5654
const openrouter = createOpenAI({
57-
compatibility: 'compatible',
5855
baseURL: 'https://openrouter.ai/api/v1',
5956
apiKey: config.openrouterKey,
6057
});
61-
return openrouter(model);
58+
return openrouter.chat(model);
6259

6360
case 'custom':
6461
if (typeof aiBaseUrl !== 'string') {
6562
throw new Error('Local AI base URL is not set');
6663
}
6764
const openaiCompatible = createOpenAI({
68-
compatibility: 'compatible',
6965
apiKey: config.customApiKey || 'bogus', // use custom API key if set, otherwise use a bogus key
7066
baseURL: aiBaseUrl,
7167
});
72-
return openaiCompatible(model);
68+
return openaiCompatible.chat(model);
7369
}
7470
}

packages/api/ai/generate.mts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { generateText, type GenerateTextResult } from 'ai';
1+
import { generateText } from 'ai';
22
import { getModel } from './config.mjs';
33
import {
44
type CodeLanguageType,
@@ -108,7 +108,6 @@ ${query}
108108
return prompt;
109109
};
110110

111-
type NoToolsGenerateTextResult = GenerateTextResult<{}>;
112111
/*
113112
* Given a user request, which is free form text describing their intent,
114113
* generate a srcbook using an LLM.
@@ -118,7 +117,7 @@ type NoToolsGenerateTextResult = GenerateTextResult<{}>;
118117
* In the future, we can parameterize this with different models, to allow
119118
* users to use different providers like Anthropic or local ones.
120119
*/
121-
export async function generateSrcbook(query: string): Promise<NoToolsGenerateTextResult> {
120+
export async function generateSrcbook(query: string): Promise<string> {
122121
const model = await getModel();
123122
const result = await generateText({
124123
model,
@@ -130,7 +129,7 @@ export async function generateSrcbook(query: string): Promise<NoToolsGenerateTex
130129
if (result.finishReason !== 'stop') {
131130
console.warn('Generated a srcbook, but finish_reason was not "stop":', result.finishReason);
132131
}
133-
return result;
132+
return result.text;
134133
}
135134

136135
export async function healthcheck(): Promise<string> {

packages/api/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@
2323
},
2424
"dependencies": {
2525
"@ai-sdk/anthropic": "catalog:",
26-
"@ai-sdk/google": "^1.0.3",
26+
"@ai-sdk/google": "catalog:",
2727
"@ai-sdk/openai": "catalog:",
28-
"@ai-sdk/provider": "^1.0.1",
28+
"@ai-sdk/provider": "catalog:",
2929
"@srcbook/shared": "workspace:^",
30-
"ai": "^3.4.33",
30+
"ai": "catalog:",
3131
"better-sqlite3": "^11.3.0",
3232
"cors": "^2.8.5",
3333
"depcheck": "^1.4.7",

packages/api/server/http.mts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ router.post('/generate', cors(), async (req, res) => {
150150
try {
151151
posthog.capture({ event: 'user generated srcbook with AI', properties: { query } });
152152
const result = await generateSrcbook(query);
153-
const srcbookDir = await importSrcbookFromSrcmdText(result.text);
153+
const srcbookDir = await importSrcbookFromSrcmdText(result);
154154
return res.json({ error: false, result: { dir: srcbookDir } });
155155
} catch (e) {
156156
const error = e as unknown as Error;

packages/shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"prepublishOnly": "npm run build"
1414
},
1515
"dependencies": {
16-
"@ai-sdk/google": "1.0.1",
16+
"@ai-sdk/google": "catalog:",
1717
"@scure/base": "^1.1.8",
1818
"zod": "catalog:"
1919
},

0 commit comments

Comments
 (0)