Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b6be653
chore: migrate toolchain to oxc + TypeScript 7 + vite 8
AlemTuzlak Jul 15, 2026
97651ca
ci: apply automated fixes
autofix-ci[bot] Jul 15, 2026
2dfd377
fix(examples): pin example apps to vite 7
AlemTuzlak Jul 15, 2026
a26e4a1
fix: unblock example builds + ai-mcp CI timeout under the new toolchain
AlemTuzlak Jul 15, 2026
50eba98
chore(examples): upgrade nitro to latest
tombeckenham Jul 16, 2026
69d1752
feat(examples): move React Start examples to nitro 3 + vite 8
tombeckenham Jul 16, 2026
675d9ed
chore(examples): drop stray route-dir test in ts-react-chat
tombeckenham Jul 16, 2026
b002641
chore(examples): use vite 8 native tsconfig paths, drop vite-tsconfig…
tombeckenham Jul 16, 2026
44c2359
ci: apply automated fixes
autofix-ci[bot] Jul 16, 2026
c74507d
feat(examples): move ts-solid-chat to vite 8
tombeckenham Jul 16, 2026
079aa2b
feat(ai-solid-ui): build on vite 8 via vite-plugin-solid
tombeckenham Jul 16, 2026
bc5c5e9
fix: align dep ranges to satisfy sherif (happy-dom, dockerode, isolat…
tombeckenham Jul 16, 2026
5293574
Merge remote-tracking branch 'origin/main' into feat/oxc-ts7-vite8-to…
AlemTuzlak Jul 20, 2026
42c9c4f
ci: apply automated fixes
autofix-ci[bot] Jul 20, 2026
258da33
Merge remote-tracking branch 'origin/main' into worktree-curious-fora…
AlemTuzlak Jul 21, 2026
f54b284
fix: align ts-group-chat nitro version to fix sherif
AlemTuzlak Jul 21, 2026
85c86aa
fix: resolve oxlint/knip failures from main merge under new toolchain
AlemTuzlak Jul 21, 2026
d3c053a
chore: consume @tanstack/vite-config via pkg.pr.new, drop patch + dts…
AlemTuzlak Jul 21, 2026
54e5d31
chore: use @tanstack/vite-config@0.6.0 (released dts-5/Vite-8 fix)
AlemTuzlak Jul 21, 2026
4ba5247
chore: use kiira@0.6.0 (native TS7 engine), drop kiira TS6 shim
AlemTuzlak Jul 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .agent/self-learning/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ If a `Use when ...` condition matches the current task, read the full lesson fil
- [update-docs-with-new-cases](lessons/2026-05-19-update-docs-with-new-cases.md) — Use when adding a new use case, capability, or behavior change to tanstack/ai — public docs that cover the surface need updating in the same PR
- [authoring-kiira-doc-snippets](lessons/2026-06-23-authoring-kiira-doc-snippets.md) — Use when writing or fixing TS/TSX code samples in docs/\*\* so they type-check under kiira AND read as idiomatic, type-safe examples (no declare const / ambient magic / group-rename / input:any / as casts)
- [kiira-ci-setup](lessons/2026-06-23-kiira-ci-setup.md) — Use when running, configuring, or debugging kiira in tanstack/ai — config, CI wiring, source resolution (ai-angular exclusion), reading errors with --verbose

<!-- LESSONS:END -->
22 changes: 22 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"semi": false,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 80,
"sortPackageJson": false,
"svelte": {},
"ignorePatterns": [
"**/.nx/",
"**/.nx/cache",
"**/.svelte-kit",
"**/build",
"**/coverage",
"**/dist",
"**/docs",
"packages/ai-fal/src/image/generated/",
"pnpm-lock.yaml",
".angular",
".github"
]
}
251 changes: 251 additions & 0 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
{
"$schema": "./node_modules/oxlint/configuration_schema.json",
"plugins": [],
"jsPlugins": [
"eslint-plugin-unused-imports",
{ "name": "eslint-js", "specifier": "oxlint-plugin-eslint" }
],
"categories": {
"correctness": "off"
},
"env": {
"builtin": true
},
"ignorePatterns": [
"**/.nx/**",
"**/.svelte-kit/**",
"**/build/**",
"**/coverage/**",
"**/dist/**",
"**/snap/**",
"**/vite.config.*.timestamp-*.*"
],
"rules": {
"unused-imports/no-unused-imports": "warn"
},
"overrides": [
{
"files": ["**/*.{js,ts,tsx}"],
"rules": {
"for-direction": "error",
"no-async-promise-executor": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-constant-binary-expression": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-else-if": "error",
"no-duplicate-case": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-empty-static-block": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-fallthrough": "error",
"no-global-assign": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-nonoctal-decimal-escape": "error",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-shadow": "warn",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-unsafe-finally": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-labels": "error",
"no-unused-private-class-members": "error",
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-var": "error",
"no-with": "error",
"prefer-const": "error",
"require-yield": "error",
"use-isnan": "error",
"valid-typeof": "error",
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
"import/first": "error",
"import/newline-after-import": "error",
"import/no-commonjs": "error",
"import/no-duplicates": "error",
"@stylistic/spaced-comment": "error",
"typescript/array-type": [
"error",
{
"default": "generic",
"readonly": "generic"
}
],
"typescript/ban-ts-comment": [
"error",
{
"ts-expect-error": false,
"ts-ignore": "allow-with-description"
}
],
"typescript/consistent-type-imports": [
"error",
{
"prefer": "type-imports"
}
],
"typescript/method-signature-style": ["error", "property"],
"typescript/no-duplicate-enum-values": "error",
"typescript/no-extra-non-null-assertion": "error",
"typescript/no-inferrable-types": [
"error",
{
"ignoreParameters": true
}
],
"typescript/no-misused-new": "error",
"typescript/no-namespace": "error",
"typescript/no-non-null-asserted-optional-chain": "error",
"typescript/no-unsafe-function-type": "error",
"typescript/no-wrapper-object-types": "error",
"typescript/prefer-as-const": "error",
"typescript/prefer-for-of": "warn",
"typescript/triple-slash-reference": "error"
},
"jsPlugins": ["@stylistic/eslint-plugin"],
"env": {
"es2020": true,
"browser": true
},
"plugins": ["typescript", "import"]
},
{
"files": ["**/*.vue"],
"rules": {
"for-direction": "error",
"no-async-promise-executor": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-compare-neg-zero": "error",
"no-cond-assign": "error",
"no-constant-binary-expression": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-dupe-else-if": "error",
"no-duplicate-case": "error",
"no-empty-character-class": "error",
"no-empty-pattern": "error",
"no-empty-static-block": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-fallthrough": "error",
"no-global-assign": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-loss-of-precision": "error",
"no-misleading-character-class": "error",
"no-nonoctal-decimal-escape": "error",
"no-regex-spaces": "error",
"no-self-assign": "error",
"no-shadow": "warn",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-unsafe-finally": "error",
"no-unsafe-optional-chaining": "error",
"no-unused-labels": "error",
"no-unused-private-class-members": "error",
"no-useless-backreference": "error",
"no-useless-catch": "error",
"no-useless-escape": "error",
"no-var": "error",
"no-with": "error",
"prefer-const": "error",
"require-yield": "error",
"use-isnan": "error",
"valid-typeof": "error",
"import/consistent-type-specifier-style": ["error", "prefer-top-level"],
"import/first": "error",
"import/newline-after-import": "error",
"import/no-commonjs": "error",
"import/no-duplicates": "error",
"@stylistic/spaced-comment": "error",
"typescript/array-type": [
"error",
{
"default": "generic",
"readonly": "generic"
}
],
"typescript/ban-ts-comment": [
"error",
{
"ts-expect-error": false,
"ts-ignore": "allow-with-description"
}
],
"typescript/consistent-type-imports": [
"error",
{
"prefer": "type-imports"
}
],
"typescript/method-signature-style": ["error", "property"],
"typescript/no-duplicate-enum-values": "error",
"typescript/no-extra-non-null-assertion": "error",
"typescript/no-inferrable-types": [
"error",
{
"ignoreParameters": true
}
],
"typescript/no-misused-new": "error",
"typescript/no-namespace": "error",
"typescript/no-non-null-asserted-optional-chain": "error",
"typescript/no-unsafe-function-type": "error",
"typescript/no-wrapper-object-types": "error",
"typescript/prefer-as-const": "error",
"typescript/prefer-for-of": "warn",
"typescript/triple-slash-reference": "error"
},
"jsPlugins": ["@stylistic/eslint-plugin"],
"plugins": ["typescript", "import"],
"env": {
"browser": true
}
},
{
"files": ["packages/*/src/**/*.{ts,tsx}"],
"rules": {
"typescript/no-non-null-assertion": "error",
"typescript/no-explicit-any": "warn",
"typescript/no-floating-promises": "error",
"typescript/no-misused-promises": "error",
"typescript/await-thenable": "error",
"typescript/switch-exhaustiveness-check": "error",
"typescript/consistent-type-exports": "error",
"typescript/prefer-readonly": "error",
"typescript/ban-ts-comment": [
"error",
{
"ts-expect-error": "allow-with-description",
"ts-ignore": false,
"ts-nocheck": true,
"ts-check": false
}
],
"eslint-js/no-restricted-syntax": [
"error",
{
"selector": "TSAsExpression > TSAsExpression[typeAnnotation.type='TSUnknownKeyword']",
"message": "Avoid `as unknown as <Type>` — it bypasses TS's structural overlap check. Prefer plain `as <Type>`, fix the root cause, or opt out with `// oxlint-disable-next-line eslint-js/no-restricted-syntax -- <reason>`."
}
]
},
"plugins": ["typescript"]
}
]
}
12 changes: 0 additions & 12 deletions .prettierignore

This file was deleted.

2 changes: 1 addition & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"oxc.oxc-vscode",
"vitest.explorer",
"nrwl.angular-console",
"svelte.svelte-vscode",
Expand Down
24 changes: 15 additions & 9 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ TanStack AI is a type-safe, provider-agnostic AI SDK for building AI-powered app

- **Package Manager**: pnpm@10.17.0 (required)
- **Build System**: Nx for task orchestration and caching
- **TypeScript**: 5.9.3
- **TypeScript**: 7.0.2 (native Go compiler). Framework build/typecheck tools
that still need the pre-7 JS Compiler API (svelte-package, svelte-check,
vue-tsc, kiira, knip) run against the `@typescript/typescript6` (6.0.2) shim
via `pnpm-workspace.yaml` packageExtensions; the framework packages
themselves stay pinned to 5.9.3. See that file's comments.
- **Testing**: Vitest for unit tests
- **Linting**: ESLint with custom TanStack config
- **Formatting**: Prettier
- **Linting**: oxlint (incl. type-aware rules via `oxlint-tsgolint`); a few
ESLint-compat rules run through oxlint's JS-plugin layer
(`oxlint-plugin-eslint`, `eslint-plugin-unused-imports`, `@stylistic`)
- **Formatting**: oxfmt

Run `pnpm install` before starting any task and again after every merge with
`main`.
Expand All @@ -32,7 +38,7 @@ pnpm test:pr
# Run specific test suites
pnpm test:lib # Run unit tests for affected packages
pnpm test:lib:dev # Watch mode for unit tests
pnpm test:eslint # Lint affected packages
pnpm test:oxlint # Lint affected packages (oxlint, incl. type-aware)
pnpm test:types # Type check affected packages
pnpm test:build # Verify build artifacts with publint
pnpm test:coverage # Generate coverage reports
Expand All @@ -53,7 +59,7 @@ cd packages/ai
pnpm test:lib # Run tests for this package
pnpm test:lib:dev # Watch mode
pnpm test:types # Type check
pnpm test:eslint # Lint
pnpm test:oxlint # Lint (oxlint)
```

### Building
Expand All @@ -73,7 +79,7 @@ pnpm dev # alias for watch
### Code Quality

```bash
pnpm format # Format all files with Prettier
pnpm format # Format all files with oxfmt
```

### Changesets (Release Management)
Expand Down Expand Up @@ -214,7 +220,7 @@ Each framework integration uses the headless `ai-client` under the hood.
4. Run tests: `pnpm test:lib` (or package-specific tests)
5. Run E2E tests: `pnpm --filter @tanstack/ai-e2e test:e2e`
6. Run type checks: `pnpm test:types`
7. Run linter: `pnpm test:eslint`
7. Run linter: `pnpm test:oxlint`
8. Format code: `pnpm format`
9. Verify build: `pnpm test:build` or `pnpm build`

Expand All @@ -230,14 +236,14 @@ The single canonical command is:
pnpm test:pr
```

This runs the exact target set the `PR` workflow runs in CI: `nx affected --targets=test:sherif,test:knip,test:docs,test:kiira,test:eslint,test:lib,test:types,test:build,build`. There is **no** `--exclude=examples/**,testing/**` carve-out — the example apps and `testing/` packages are included, so Nx runs whatever of these targets they define (in practice `build` and `test:types`). Including them means `test:types` is checked at the call sites where the library is actually consumed, catching call-site type regressions that only manifest there (see issue #820). To type-check just the example apps + `testing/` packages locally, run `nx run-many --targets=test:types --projects=examples/**,testing/**`.
This runs the exact target set the `PR` workflow runs in CI: `nx affected --targets=test:sherif,test:knip,test:docs,test:kiira,test:oxlint,test:lib,test:types,test:build,build`. There is **no** `--exclude=examples/**,testing/**` carve-out — the example apps and `testing/` packages are included, so Nx runs whatever of these targets they define (in practice `build` and `test:types`). Including them means `test:types` is checked at the call sites where the library is actually consumed, catching call-site type regressions that only manifest there (see issue #820). To type-check just the example apps + `testing/` packages locally, run `nx run-many --targets=test:types --projects=examples/**,testing/**`.

If you can't run `test:pr` (e.g. it's too slow on your machine), at minimum run each of these and confirm they're green before pushing:

- `pnpm test:sherif` — workspace consistency
- `pnpm test:knip` — unused dependencies
- `pnpm test:docs` — doc link verification
- `pnpm test:eslint` — lint
- `pnpm test:oxlint` — lint (oxlint, incl. type-aware)
- `pnpm test:types` — typecheck (packages)
- `nx run-many --targets=test:types --projects=examples/**,testing/**` — typecheck the example apps + `testing/` packages
- `pnpm test:lib` — unit tests
Expand Down
2 changes: 1 addition & 1 deletion codemods/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
"jscodeshift": "^17.1.1",
"prettier": "^3.7.4",
"typescript": "5.9.3",
"vitest": "^4.0.14"
"vitest": "^4.1.10"
}
}
Loading
Loading