feat(ai-octane): port Octane bindings from @octanejs/tanstack-ai - #1000
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (51)
🚧 Files skipped from review as they are similar to previous changes (48)
Included review availability: Your plan includes up to 8 reviews per rolling hour; 7 remain after this review. 📝 WalkthroughWalkthroughThe PR adds ChangesTanStack AI Octane binding
Estimated code review effort: 4 (Complex) | ~60 minutes Merge Risk: 🟡 Moderate · up to This PR adds the Octane binding package and its consumer-compiled hook surface. The change has no supplied functional review findings, but the PR currently has merge conflicts, so it is not merge-ready until those conflicts are resolved and checks are rerun. Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🚀 Changeset Version Preview17 package(s) bumped directly, 34 bumped as dependents. 🟥 Major bumps
🟨 Minor bumps
🟩 Patch bumps
|
|
View your CI Pipeline Execution ↗ for commit 4d8fdd8
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-byteplus
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-snippets
@tanstack/ai-codex
@tanstack/ai-cohere
@tanstack/ai-devtools-core
@tanstack/ai-durable-stream
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-daytona
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-isolate-quickjs-bun
@tanstack/ai-llmgateway
@tanstack/ai-mcp
@tanstack/ai-memory
@tanstack/ai-mistral
@tanstack/ai-octane
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-perplexity
@tanstack/ai-persistence
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vercel-gateway
@tanstack/ai-vertex
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (9)
packages/ai-octane/package.json (1)
48-53: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftWire the declaration tests into the type-check path.
test:typeschecks onlysrc/; it never invokestypetests/tsconfig.json. After resolving the four documented type-test errors, add that project to the package or CI type-check command so the public declaration surface is actually verified.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/package.json` around lines 48 - 53, Update the test:types script in package.json to also run the declaration tests using typetests/tsconfig.json, while preserving the existing src type-check. Ensure the type-check path verifies both the package sources and public declaration surface.packages/ai-octane/tests/ssr/server.test.ts (1)
1-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winColocate this test with the source it covers.
This unit test is under
tests/ssr/, while the exercisedServerChatsource is undertests/_fixtures/. Move the test beside that fixture (or the production source it validates) and update the relative import.As per coding guidelines, unit tests in
**/*.test.tsmust live alongside the source they cover.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/tests/ssr/server.test.ts` around lines 1 - 14, Move the SSR test alongside the ServerChat fixture it exercises, rather than keeping it under tests/ssr/. Update the relative ServerChat import to match the new colocated location, while preserving the existing test behavior and assertions.Source: Coding guidelines
packages/ai-octane/tests/conformance/use-chat.test.ts (1)
495-511: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDead
onConnectreturn-value logic in the reload test.
MockConnectionAdapterOptions.onConnectis typed=> voidand its return value is discarded bycreateMockConnectionAdapter(_ai-client-test-utils.tslines 87-94), socallCount/return chunks2here does nothing — the second stream comes fromadapter2viarerender. Drop the misleading branch.♻️ Proposed cleanup
const chunks1 = createTextChunks('First response'); const chunks2 = createTextChunks('Second response'); - let callCount = 0; - - const adapter = createMockConnectionAdapter({ - chunks: chunks1, - onConnect: () => { - callCount++; - // Return different chunks on second call - if (callCount === 2) { - return chunks2; - } - return undefined; - }, - }); + const adapter = createMockConnectionAdapter({ chunks: chunks1 }); // Create a new adapter for the second call const adapter2 = createMockConnectionAdapter({ chunks: chunks2 });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/tests/conformance/use-chat.test.ts` around lines 495 - 511, Remove the unused callCount state and onConnect callback branch from the adapter setup in the reload test. Keep the first adapter configured only with chunks1, and preserve the second-stream behavior through adapter2 and the existing rerender flow.packages/ai-octane/typetests/use-chat.test-d.tsx (1)
9-47: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDrop the duplicated Standard Schema shapes and use the real exports.
@standard-schema/specis a direct dev dependency for@tanstack/ai-octane, and the same package importsStandardJSONSchemaV1from it in other tests. ImportStandardJSONSchemaV1andStandardSchemaV1from@standard-schema/spechere and replaceStandardJSONSchemaLike/StandardSchemaLikewith the official types.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/typetests/use-chat.test-d.tsx` around lines 9 - 47, Replace the hand-rolled StandardSchemaLike and StandardJSONSchemaLike declarations in the type test with imports of StandardSchemaV1 and StandardJSONSchemaV1 from `@standard-schema/spec`, then update all usages to reference the official types while preserving the existing type assertions.packages/ai-octane/tests/conformance/use-chat-options-probe.test.ts (1)
11-22: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
toExtendfor these type assertions.
toMatchTypeOfis deprecated in the project’s Vitest 4.x API; replace these assertions withexpectTypeOf<...>().not.toExtend<...>()/.toExtend<...>()instead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/tests/conformance/use-chat-options-probe.test.ts` around lines 11 - 22, Replace the deprecated toMatchTypeOf assertions in the UseChatOptions type probe with Vitest 4.x toExtend assertions, preserving the existing positive checks for connection and fetcher and negative checks for the empty and combined options.packages/ai-octane/src/use-generation.tsrx.d.ts (1)
44-59: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win
useGeneration's untypedgenerateinput forces casts in every specialized hook.UseGenerationReturn<TOutput>never parameterizesgenerateonTInput(it's hardcoded toRecord<string, any>), so hooks built on top ofuseGenerationmust cast the return value back to the correct input type instead of getting it for free.
packages/ai-octane/src/use-generation.tsrx.d.ts#L44-L59: add aTInputgeneric toUseGenerationReturnand thread it through theuseGenerationdeclaration (Line 79-81) sogenerateis typed(input: TInput) => Promise<void>.packages/ai-octane/src/use-generate-audio.tsrx#L117: once the base type carriesTInput, drop thegenerate as (input: AudioGenerateInput) => Promise<void>cast.packages/ai-octane/src/use-generate-image.tsrx#L119: drop the equivalentgenerate as (input: ImageGenerateInput) => Promise<void>cast.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/src/use-generation.tsrx.d.ts` around lines 44 - 59, Parameterize UseGenerationReturn with a TInput generic and type generate as accepting TInput; thread that generic through the useGeneration declaration. In packages/ai-octane/src/use-generate-audio.tsrx:117 and packages/ai-octane/src/use-generate-image.tsrx:119, remove the generate casts and use the typed return directly.packages/ai-octane/src/realtime-types.ts (1)
1-10: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse the same
AnyClientToolimport path in this file.
realtime-types.tsimportsAnyClientToolfrom@tanstack/ai, while the siblinguse-chat.tsrximports it from@tanstack/ai/client. Standardize the import to the same package subpath used by the surrounding Octane files to keep the package imports consistent.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/src/realtime-types.ts` around lines 1 - 10, Update the AnyClientTool import in realtime-types.ts to use the `@tanstack/ai/client` subpath, matching the import used by sibling Octane files such as use-chat.tsrx, while leaving the other type imports unchanged.packages/ai-octane/src/use-realtime-chat.tsrx (1)
14-16: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winShared mutable module-level arrays returned as fallback values.
emptyFrequencyData/emptyTimeDomainDataare singletons shared by everyuseRealtimeChatinstance and returned directly (no copy) from theget*Dataaccessors. If any caller writes into the returned array (common for audio-visualization smoothing code), it would corrupt this shared constant for all other instances/components. A cheap mitigation is to freeze them so accidental writes fail loudly instead of silently leaking state.🛡️ Optional defensive fix
-const emptyFrequencyData = new Uint8Array(128) -const emptyTimeDomainData = new Uint8Array(128).fill(128) +const emptyFrequencyData = Object.freeze(new Uint8Array(128)) +const emptyTimeDomainData = Object.freeze(new Uint8Array(128).fill(128))Also applies to: 244-266
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/src/use-realtime-chat.tsrx` around lines 14 - 16, Protect the shared fallback arrays used by useRealtimeChat by preventing mutation of emptyFrequencyData and emptyTimeDomainData before they are returned by the get*Data accessors. Ensure accidental writes fail loudly while preserving their current fallback values and accessor behavior.packages/ai-octane/src/use-generation.tsrx (1)
1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift
use-generate-video.tsrxduplicatesuse-generation.tsrx's client lifecycle instead of composing over it.Unlike
use-generate-speech.tsrx,use-summarize.tsrx, anduse-transcription.tsrx— which all delegate to the shareduseGenerationhook —use-generate-video.tsrxre-implements the sameoptionsRef/useMemoclient-creation/body-sync-effect/mount-dispose/generate-stop-reset pattern from scratch, just addingjobId/videoStatusstate. This duplication is the kind of thing that lets logic diverge silently, as demonstrated by the devtools spread-order bug found only inuse-generation.tsrx(fixed independently, and correctly, in the video hook).
packages/ai-octane/src/use-generation.tsrx#L97-217: extract the shared client-lifecycle scaffolding (optionsRef, memoized client construction, body-sync effect, mount/dispose effect, generate/stop/reset callbacks) into a reusable internal helper that bothuseGenerationand video-specific state extensions can compose over.packages/ai-octane/src/use-generate-video.tsrx#L1-245: replace the duplicated lifecycle logic with a call into that shared helper, layeringjobId/videoStatusstate and the extraonJobCreated/onStatusUpdatecallbacks on top instead of reimplementing the core client wiring.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-octane/src/use-generation.tsrx` at line 1, The shared client lifecycle is duplicated between useGeneration and useGenerateVideo. Extract the optionsRef, memoized client creation, body synchronization, mount/dispose handling, and generate/stop/reset callbacks from useGeneration into a reusable internal helper, then have both hooks compose it; update use-generate-video to layer jobId/videoStatus state and onJobCreated/onStatusUpdate callbacks over the helper while preserving existing behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ai-octane/package.json`:
- Line 59: Update the `@tanstack/ai` dependency declaration in the package
manifest from workspace:^ to workspace:*, preserving it as an internal workspace
dependency.
In `@packages/ai-octane/src/use-audio-recorder.tsrx.d.ts`:
- Around line 43-44: Update the transforming useAudioRecorder overload so its
UseAudioRecorderOptions<TOnComplete> parameter requires a defined onComplete
callback, preventing options without onComplete from matching it and inferring
unknown. Preserve the optional-options overload for untransformed usage and its
AudioRecording return types.
In `@packages/ai-octane/src/use-chat.tsrx`:
- Around line 182-204: The wire-payload synchronization effects currently apply
inconsistent undefined handling. Update the effects around
ChatClient.updateOptions so body and forwardedProps preserve the client’s
existing values when undefined, while the context effect passes options.context
unchanged to preserve its key-presence clearing behavior; do not add a guard
that changes context semantics.
In `@packages/ai-octane/src/use-generation.tsrx`:
- Around line 129-134: Update the devtools configuration in useGeneration so
opts.devtools is spread before the hardcoded hookName and framework values,
ensuring callers cannot override the Octane identification while preserving
their other devtools options.
In `@packages/ai-octane/tests/conformance/test-utils.ts`:
- Around line 27-33: Update renderUseChat to default its optional options
parameter to an empty UseChatOptions object before passing it to renderHook and
useChat. Remove the non-null assertion and ensure both omitted and explicitly
provided options remain valid.
---
Nitpick comments:
In `@packages/ai-octane/package.json`:
- Around line 48-53: Update the test:types script in package.json to also run
the declaration tests using typetests/tsconfig.json, while preserving the
existing src type-check. Ensure the type-check path verifies both the package
sources and public declaration surface.
In `@packages/ai-octane/src/realtime-types.ts`:
- Around line 1-10: Update the AnyClientTool import in realtime-types.ts to use
the `@tanstack/ai/client` subpath, matching the import used by sibling Octane
files such as use-chat.tsrx, while leaving the other type imports unchanged.
In `@packages/ai-octane/src/use-generation.tsrx`:
- Line 1: The shared client lifecycle is duplicated between useGeneration and
useGenerateVideo. Extract the optionsRef, memoized client creation, body
synchronization, mount/dispose handling, and generate/stop/reset callbacks from
useGeneration into a reusable internal helper, then have both hooks compose it;
update use-generate-video to layer jobId/videoStatus state and
onJobCreated/onStatusUpdate callbacks over the helper while preserving existing
behavior.
In `@packages/ai-octane/src/use-generation.tsrx.d.ts`:
- Around line 44-59: Parameterize UseGenerationReturn with a TInput generic and
type generate as accepting TInput; thread that generic through the useGeneration
declaration. In packages/ai-octane/src/use-generate-audio.tsrx:117 and
packages/ai-octane/src/use-generate-image.tsrx:119, remove the generate casts
and use the typed return directly.
In `@packages/ai-octane/src/use-realtime-chat.tsrx`:
- Around line 14-16: Protect the shared fallback arrays used by useRealtimeChat
by preventing mutation of emptyFrequencyData and emptyTimeDomainData before they
are returned by the get*Data accessors. Ensure accidental writes fail loudly
while preserving their current fallback values and accessor behavior.
In `@packages/ai-octane/tests/conformance/use-chat-options-probe.test.ts`:
- Around line 11-22: Replace the deprecated toMatchTypeOf assertions in the
UseChatOptions type probe with Vitest 4.x toExtend assertions, preserving the
existing positive checks for connection and fetcher and negative checks for the
empty and combined options.
In `@packages/ai-octane/tests/conformance/use-chat.test.ts`:
- Around line 495-511: Remove the unused callCount state and onConnect callback
branch from the adapter setup in the reload test. Keep the first adapter
configured only with chunks1, and preserve the second-stream behavior through
adapter2 and the existing rerender flow.
In `@packages/ai-octane/tests/ssr/server.test.ts`:
- Around line 1-14: Move the SSR test alongside the ServerChat fixture it
exercises, rather than keeping it under tests/ssr/. Update the relative
ServerChat import to match the new colocated location, while preserving the
existing test behavior and assertions.
In `@packages/ai-octane/typetests/use-chat.test-d.tsx`:
- Around line 9-47: Replace the hand-rolled StandardSchemaLike and
StandardJSONSchemaLike declarations in the type test with imports of
StandardSchemaV1 and StandardJSONSchemaV1 from `@standard-schema/spec`, then
update all usages to reference the official types while preserving the existing
type assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 9f64c274-7e5e-4751-bc09-8fbc9beedfb0
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (49)
.changeset/ai-octane-port.mdpackages/ai-octane/README.mdpackages/ai-octane/package.jsonpackages/ai-octane/src/index.tspackages/ai-octane/src/realtime-types.tspackages/ai-octane/src/types.tspackages/ai-octane/src/use-audio-recorder.tsrxpackages/ai-octane/src/use-audio-recorder.tsrx.d.tspackages/ai-octane/src/use-chat.tsrxpackages/ai-octane/src/use-chat.tsrx.d.tspackages/ai-octane/src/use-generate-audio.tsrxpackages/ai-octane/src/use-generate-audio.tsrx.d.tspackages/ai-octane/src/use-generate-image.tsrxpackages/ai-octane/src/use-generate-image.tsrx.d.tspackages/ai-octane/src/use-generate-speech.tsrxpackages/ai-octane/src/use-generate-speech.tsrx.d.tspackages/ai-octane/src/use-generate-video.tsrxpackages/ai-octane/src/use-generate-video.tsrx.d.tspackages/ai-octane/src/use-generation.tsrxpackages/ai-octane/src/use-generation.tsrx.d.tspackages/ai-octane/src/use-mcp-app-bridge.tsrxpackages/ai-octane/src/use-mcp-app-bridge.tsrx.d.tspackages/ai-octane/src/use-realtime-chat.tsrxpackages/ai-octane/src/use-realtime-chat.tsrx.d.tspackages/ai-octane/src/use-summarize.tsrxpackages/ai-octane/src/use-summarize.tsrx.d.tspackages/ai-octane/src/use-transcription.tsrxpackages/ai-octane/src/use-transcription.tsrx.d.tspackages/ai-octane/status.jsonpackages/ai-octane/tests/_fixtures/server.tsrxpackages/ai-octane/tests/conformance/_ai-client-test-utils.tspackages/ai-octane/tests/conformance/exports.test.tspackages/ai-octane/tests/conformance/test-setup.tspackages/ai-octane/tests/conformance/test-utils.tspackages/ai-octane/tests/conformance/use-audio-recorder.test.tspackages/ai-octane/tests/conformance/use-chat-fetcher.test.tspackages/ai-octane/tests/conformance/use-chat-options-probe.test.tspackages/ai-octane/tests/conformance/use-chat-structured-output.test.tspackages/ai-octane/tests/conformance/use-chat.test.tspackages/ai-octane/tests/conformance/use-generation.test.tspackages/ai-octane/tests/conformance/use-mcp-app-bridge.test.tspackages/ai-octane/tests/conformance/use-realtime-chat.test.tspackages/ai-octane/tests/ssr/server.test.tspackages/ai-octane/tsconfig.jsonpackages/ai-octane/typetests/tsconfig.jsonpackages/ai-octane/typetests/use-chat.test-d.tsxpackages/ai-octane/typetests/use-realtime-chat.test-d.tspackages/ai-octane/vite.config.tspnpm-workspace.yaml
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ai-octane/src/use-generation.tsrx.d.ts`:
- Around line 50-52: Update UseGenerationReturn to accept a TInput generic and
change generate to accept TInput instead of Record<string, any>. Propagate the
TInput parameter through useGeneration’s return type so required and narrow
input fields remain type-checked.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 18166fa5-57f5-41ef-a0e4-126822d4c4e4
📒 Files selected for processing (29)
packages/ai-octane/src/index.tspackages/ai-octane/src/realtime-types.tspackages/ai-octane/src/types.tspackages/ai-octane/src/use-audio-recorder.tsrx.d.tspackages/ai-octane/src/use-chat.tsrx.d.tspackages/ai-octane/src/use-generate-audio.tsrx.d.tspackages/ai-octane/src/use-generate-image.tsrx.d.tspackages/ai-octane/src/use-generate-speech.tsrx.d.tspackages/ai-octane/src/use-generate-video.tsrx.d.tspackages/ai-octane/src/use-generation.tsrx.d.tspackages/ai-octane/src/use-mcp-app-bridge.tsrx.d.tspackages/ai-octane/src/use-realtime-chat.tsrx.d.tspackages/ai-octane/src/use-summarize.tsrx.d.tspackages/ai-octane/src/use-transcription.tsrx.d.tspackages/ai-octane/tests/conformance/_ai-client-test-utils.tspackages/ai-octane/tests/conformance/exports.test.tspackages/ai-octane/tests/conformance/test-setup.tspackages/ai-octane/tests/conformance/test-utils.tspackages/ai-octane/tests/conformance/use-audio-recorder.test.tspackages/ai-octane/tests/conformance/use-chat-fetcher.test.tspackages/ai-octane/tests/conformance/use-chat-options-probe.test.tspackages/ai-octane/tests/conformance/use-chat-structured-output.test.tspackages/ai-octane/tests/conformance/use-chat.test.tspackages/ai-octane/tests/conformance/use-generation.test.tspackages/ai-octane/tests/conformance/use-mcp-app-bridge.test.tspackages/ai-octane/tests/conformance/use-realtime-chat.test.tspackages/ai-octane/tests/ssr/server.test.tspackages/ai-octane/typetests/use-chat.test-d.tsxpackages/ai-octane/typetests/use-realtime-chat.test-d.ts
🚧 Files skipped from review as they are similar to previous changes (26)
- packages/ai-octane/tests/conformance/use-chat-options-probe.test.ts
- packages/ai-octane/src/use-realtime-chat.tsrx.d.ts
- packages/ai-octane/tests/conformance/exports.test.ts
- packages/ai-octane/typetests/use-realtime-chat.test-d.ts
- packages/ai-octane/tests/ssr/server.test.ts
- packages/ai-octane/tests/conformance/use-mcp-app-bridge.test.ts
- packages/ai-octane/src/use-generate-audio.tsrx.d.ts
- packages/ai-octane/src/use-chat.tsrx.d.ts
- packages/ai-octane/tests/conformance/use-chat-fetcher.test.ts
- packages/ai-octane/tests/conformance/test-setup.ts
- packages/ai-octane/src/use-mcp-app-bridge.tsrx.d.ts
- packages/ai-octane/src/realtime-types.ts
- packages/ai-octane/src/use-generate-video.tsrx.d.ts
- packages/ai-octane/tests/conformance/_ai-client-test-utils.ts
- packages/ai-octane/src/use-generate-speech.tsrx.d.ts
- packages/ai-octane/src/index.ts
- packages/ai-octane/tests/conformance/use-realtime-chat.test.ts
- packages/ai-octane/src/use-generate-image.tsrx.d.ts
- packages/ai-octane/src/use-summarize.tsrx.d.ts
- packages/ai-octane/typetests/use-chat.test-d.tsx
- packages/ai-octane/tests/conformance/use-audio-recorder.test.ts
- packages/ai-octane/tests/conformance/use-generation.test.ts
- packages/ai-octane/tests/conformance/use-chat-structured-output.test.ts
- packages/ai-octane/src/use-transcription.tsrx.d.ts
- packages/ai-octane/src/types.ts
- packages/ai-octane/tests/conformance/use-chat.test.ts
Review responseRe-evaluated all six comments as new code rather than as an untouchable port — " Fixed (ed3c8ea)
Each fix is covered by a test verified to fail when the fix is reverted — 5 type errors for the Not changing
Thanks — the four real ones were worth catching. |
On the two open itemsBoth are deliberate and confirmed with @jherr — recording the reasoning here so they don't read as oversights. E2E coverage: blocked externally, not skipped. E2E in this repo runs against a demo app under Type asymmetry with Neither blocks review of what's here. |
tombeckenham
left a comment
There was a problem hiding this comment.
Cool stuff. Can you add some docs, and an example? e2e tests if they work with octane.
2bf7d95 to
ce5d9b9
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
tombeckenham
left a comment
There was a problem hiding this comment.
Hi @jherr, sorry I didn't get to appove this earlier. Could you please update this PR to match the new shape of ChatClient?
6906c81 to
b7e9958
Compare
bcd7c1c to
03483da
Compare
|
ChatClient catch-up is in. Docs are in:
Snippets in those pages are the example. There is no new E2E is still blocked on an official Octane build of TanStack Start. That is recorded in The two CodeRabbit threads that remain open ( |
6a36613 to
e50f2ad
Compare
Adds `@tanstack/ai-octane`, an Octane binding for TanStack AI. This is a port of `@octanejs/tanstack-ai@0.0.11`, which lived in the octanejs/octane repo as a temporary stopgap; the code moves here essentially unchanged apart from the rename. Covers the `@tanstack/ai-react` hook surface (useChat, useRealtimeChat, useMcpAppBridge, useGeneration, useGenerateImage/Audio/Speech/Video, useTranscription, useSummarize, useAudioRecorder) plus the 30 `@tanstack/ai-client` convenience re-exports, reusing `@tanstack/ai` and `@tanstack/ai-client` unchanged. SSR through `octane/server` is tested. Packaging: like Svelte packages shipping `.svelte`, this one publishes uncompiled source. The hook modules are `.tsrx`, compiled by the consumer's Octane plugin, so there is no `dist`/`build` target and no publint `test:build`; `octane` is a required peer. The `.tsrx.d.ts` companions are checked declaration emits, so `tsc` still verifies the full public generic surface. Deviations from a byte-for-byte move, all recorded in status.json: - Conformance runs on happy-dom rather than jsdom. This repo pins jsdom ^27, whose `Blob` has no `arrayBuffer()` (Octane pins ^29, which does) and the useAudioRecorder cases need it. Bumping jsdom for one package would break sherif's cross-package version consistency. - Two useChat cases asserted that a second concurrent sendMessage is dropped. #900 made client-side queueing the default, so both now assert queue-and-deliver-in-order, mirroring the current ai-react tests. The hook needed no change — queueing lives in ChatClient. - The differential parity test stays in the Octane repo: it byte-compares streamed output against real @tanstack/ai-react, which would make a sibling workspace package a pinned test dependency. - Unused vendored test helpers were dropped rather than carried as dead code (knip). - The generated .tsrx.d.ts companions are excluded from lint; a regeneration would undo any hand-fix. Known gap: the port is baselined against @tanstack/ai-react 0.17.0 while this repo is at 0.18.1. The interrupts overhaul (#970) and server persistence / browser-refresh durability (#984) are not yet reflected in the Octane hooks, and `typetests/` is therefore not wired into CI — its 4 errors are confined to one tool-input-inference case that fails identically against @tanstack/ai-react, so it is not a port defect. status.json lists the exact type-surface delta. Parity catch-up is follow-up work. pnpm-workspace.yaml excludes octane@0.1.17 and @octanejs/testing-library@0.1.14 from minimumReleaseAge: Octane publishes the pair in lockstep (testing-library pins an exact octane peer) and releases roughly daily, so the newest pair is essentially always inside the 24h window. 143 tests pass (142 conformance + 1 SSR), no skips or todos. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review of the port surfaced real defects rather than style nits. Treating this as new code rather than an untouchable move, they are fixed here and tracked upstream (#1001, #1002, #1003) so the other adapters can follow. - useAudioRecorder's transforming overload now requires `onComplete`. Without that constraint an options object carrying only unrelated keys (`useAudioRecorder({ onError })`) still matched it, `TOnComplete` inferred as `unknown`, and `recording`/`stop()` collapsed to `unknown` — so passing any option silently cost you the AudioRecording type. Confirmed to reproduce in @tanstack/ai-react. - useGeneration spreads caller `devtools` metadata before the hardcoded `framework`/`hookName`, so a caller can no longer misattribute this binding in the devtools. The port was internally inconsistent here: useChat and useGenerateVideo already ordered it this way. Upstream, only ai-react is affected — ai-vue and ai-solid are already correct. - UseGenerationReturn is now `<TInput, TOutput>` and types `generate` as `(input: TInput)` rather than casting it to `(input: Record<string, any>)`, so required and narrow input fields are checked at the call site. This is the one place the public type surface differs in shape from ai-react; the runtime surface is unchanged, and no other module referenced the type (the media hooks declare their own). Also hardens the renderUseChat test helper to default its options instead of asserting `options!`, which would have passed `undefined` into a hook that reads options eagerly. typetests/ is now wired into CI via `test:types`. It previously could not be: the upstream tool-input-inference case failed because its hand-rolled StandardJSONSchemaLike stand-in doesn't thread through @tanstack/ai's inference. That stand-in existed only because @standard-schema/spec wasn't directly resolvable in the Octane repo — it is here, so tool inputs now use real Zod, matching @tanstack/ai-client's own type tests. The outputSchema tests keep a structural stand-in deliberately, to prove inference works for any spec-conforming validator rather than one library. Each fix is covered by a test that was verified to fail when the fix is reverted: 5 type errors for the TInput widening, 3 for the audio-recorder overload, and a failing devtools assertion (`framework: 'react'` leaking through) for the spread order. 147 tests pass (was 143); src and typetests both type-check. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
E2E in this repo runs against a demo app under testing/e2e, which is TanStack Start-based. An Octane build of TanStack Start exists but is not officially released, so the app can't be built yet. Holding until it ships rather than working around it. Recording it in status.json so the gap reads as a known external blocker rather than an oversight against the repo's E2E policy. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Wire threadId identity, queue, interrupts, attach/detach, and SendMessageOptions. Return the onResponse promise so ChatClient can await it. Revert the unrelated ai-sandbox snapshot assertion so this PR matches main.
Document install, a server SSE route, and useChat for Octane apps. Snippets in the docs are the example. There is no new example app.
Octane component syntax is not TypeScript. Keep one typed hook sample and mark UI blocks ignore.
Install octane as a kiira external package so the Octane docs type-check for real. Rewrite TSRX fences as standard TSX. Keep the Express snippet on ignore, matching the rest of the repo.
e50f2ad to
4d8fdd8
Compare
You can now use TanStack AI hooks in an Octane app:
useChat, generation, transcription, and the rest. Import from@tanstack/ai-octane. The hook surface matches currentChatClient(threadId, queue, interrupts,attach/detach).Changes
Adds
@tanstack/ai-octane, an Octane binding for TanStack AI.This ports
@octanejs/tanstack-ai@0.0.11into this repo under the framework-adapter name.useChatis caught up to the current ChatClient shape (queue, interrupts,threadIdidentity,attach/detach,SendMessageOptions).The package publishes uncompiled
.tsrxsource. The consumer Octane plugin compiles it.octaneis a required peer.Docs: Quick Start: Octane and API. Those snippets are the example. There is no new example app.
The Octane UI snippets are standard TSX and type-check in
pnpm test:kiira.octaneis a kiiraexternalPackagesentry. The Express server fence stays onignore(same reason as other Express fences in this repo).E2E is still blocked: the suite runs against a TanStack Start app, and an official Octane build of Start is not released yet. Recorded in
packages/ai-octane/status.json.Checklist
pnpm run test:pr.docs/for this change, or this change is not user-facing.pnpm changeset), or this PR does not change a published package.Release Impact
Testing
pnpm --filter @tanstack/ai-octane test:lib(158 passed)pnpm --filter @tanstack/ai-octane test:types(passed)pnpm --filter @tanstack/ai-octane test:oxlint(0 errors on source)pnpm test:docs(no broken links)pnpm test:kiira(1096 snippets passed, 0 failed)mainwith no leftover conflict markerspnpm test:pron this machine@tanstack/ai-octaneandoctanein an Octane app.useChatsnippet fromdocs/getting-started/quick-start-octane.md.packages/ai-octane/tests/conformance/use-chat.test.tscovers queue, interrupts,threadId, and attach/detach.pnpm test:kiiracovers the doc snippets.Public API change
Before
After
threadIdis the chat identity.idis not a hook option. Sends while busy go intoqueueunless you pass{ whenBusy: 'drop' }.Risk / rollback
New package. Existing adapters do not change. Revert the PR to undo. Octane E2E is not in this repo yet, so a wiring bug in
useChatwould show up in unit tests or in an Octane app, not intesting/e2e.