feat(plugin): rename transaction/verb to plugin, drop composition + clientTransaction, add media factories#945
feat(plugin): rename transaction/verb to plugin, drop composition + clientTransaction, add media factories#945AlemTuzlak wants to merge 11 commits into
Conversation
…n + clientTransaction
… generationPlugin
…run demux + subRuns surface
The media factories used z.object(...) at runtime, the first entry-reachable runtime zod import in the package. Since zod is only a devDependency of this deliberately schema-library-agnostic package, that bundled zod into the ESM output (dist/esm/node_modules/zod) and shifted Rollup's preserveModules root, nesting all emitted JS under dist/esm/packages/ai/src. Replace the six z.object schemas with a hand-rolled Standard Schema helper (object + required-key check), keeping the same public input types and typed req.input.
…ePlugin, flatten options, drop subRuns (solid/vue/svelte)
…st, add media-factory test
… orchestration; drop composition
…+ trim changeset stale terms
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 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 Preview19 package(s) bumped directly, 26 bumped as dependents. 🟥 Major bumps
🟨 Minor bumps
🟩 Patch bumps
|
|
View your CI Pipeline Execution ↗ for commit 250d506 ☁️ Nx Cloud last updated this comment at |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx affected --targets=test:sherif,test:knip,tes... |
❌ Failed | 12m 39s | View ↗ |
nx run-many --targets=build --exclude=examples/... |
✅ Succeeded | 2m 15s | View ↗ |
☁️ Nx Cloud last updated this comment at 2026-07-15 12:48:12 UTC
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@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-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-mcp
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@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-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |

Summary
Stacked on #942 (
feat/transaction-client-stub). This PR keeps the good part of #942 — an app-defined registry of typed capabilities behind one endpoint and one client hook — but reshapes it into a plugin API: it drops the server-side composition layer and theclientTransactionstub, renamestransaction/verb→plugin, and adds media-generation factories. Server-side composition returns later as a dedicatedworkflowPlugin.The differences from #942, in code:
1. Server:
defineTransaction/chatVerb/verb→definePlugin/chatPlugin/generationPlugin(+ media factories)#942
This PR
New media factories, all thin wrappers over the generic
generationPlugin:imagePlugin,videoPlugin,audioPlugin,speechPlugin,transcriptionPlugin,summarizePlugin. The generic escape hatch stays for custom work:2. Composition removed:
ctx.callsub-runs → client-side orchestration#942 — a "composing verb" ran siblings server-side; each
ctx.callstreamed back as a tagged sub-run of one request:This PR —
generationPlugin.executetakes onlyreq(noctx); orchestration lives in the component:Gone with it:
TransactionRunContext/ctx.call, the sub-run push channel,TRANSACTION_EVENTS, the client-side sub-run demux,TransactionSubRun, and thesubRuns/getSubRuns/onSubRunsChangesurfaces. (Server-side composition returns as a futureworkflowPlugin.)3. Client:
clientTransactionstub + nestedverbsmap → import the def value + flat options#942
This PR
The
definePluginvalue carries plugin names + kinds at runtime, sousePluginbinds off it directly — no second declaration. Importing it into the browser is safe: the adapter callbacks are inert untilhandlerruns server-side, so no credentials leak. Reserved keys (connection/id/threadId) are excluded from the per-plugin option map so a plugin can't collide with them.Rename at a glance
defineTransactiondefinePluginchatVerbchatPluginverbgenerationPlugin(+imagePlugin/videoPlugin/audioPlugin/speechPlugin/transcriptionPlugin/summarizePlugin)useTransaction/createTransactionusePlugin/createPluginclientTransactiondefinePluginvalueTransactionClientPluginClientexecute(req, ctx)+ctx.callexecute(req)+ client-side orchestrationTRANSACTION_EVENTS, sub-runs,subRunsworkflowPlugin)def.verbs/verbKinds/~verbsdef.plugins/pluginKinds/~plugins@tanstack/ai*/transaction@tanstack/ai*/pluginMedia factory input schemas are hand-rolled Standard Schemas (zod-free) so the core stays schema-library-agnostic — no runtime zod dependency is pulled into the bundle.
Test plan
pnpm test:pr(CI canonical gate)pnpm --filter @tanstack/ai-e2e test:e2eLocal (this branch): each changed package passed
test:types+test:lib; consumersts-react-chat+@tanstack/ai-e2epassedtest:typesagainst the final API; e2e plugin suite 3/3 (chat / one-shot / media);test:docs,test:kiira(794/794),test:knip,test:sherifgreen. The one-shot fulltest:pr+ full e2e were not completed locally (nx-daemon/memory stall on the dev machine — infra, not code), hence relying on CI.Follow-up (non-blocking)
runGenerationPluginStream's non-streaming branch could delegate to the existingstreamGenerationResulthelper (byte-identical behavior today) — small DRY cleanup left for later.🤖 Generated with Claude Code