@raindrop-ai/tanstack-ai
v0.0.4
Published
Raindrop integration for the TanStack AI framework (chat middleware + Workshop mirroring)
Maintainers
Keywords
Readme
@raindrop-ai/tanstack-ai
Raindrop integration for the TanStack AI framework.
Streams every chat() invocation to Raindrop (and/or a locally-running Workshop daemon) as a Raindrop event plus an OTel trace. Multiple turns sharing a TanStack threadId group under one Workshop conversation automatically.
Install
pnpm add @raindrop-ai/tanstack-ai @tanstack/aiUsage
import { chat } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai/adapters";
import { createRaindropTanstackAI } from "@raindrop-ai/tanstack-ai";
const raindrop = createRaindropTanstackAI({
writeKey: process.env.RAINDROP_WRITE_KEY,
defaults: { userId: "user-123" },
});
for await (const chunk of chat({
adapter: openaiText(),
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello" }],
middleware: [raindrop.middleware],
threadId: "convo-abc",
})) {
// …
}
await raindrop.flush();Workshop-only setups
A writeKey is optional. When omitted, the middleware mirrors spans + events to a reachable local Workshop daemon (RAINDROP_LOCAL_DEBUGGER, RAINDROP_WORKSHOP, or http://localhost:5899 when NODE_ENV=development). Pass localWorkshopUrl: false to disable all local mirroring.
Application Git identity
Each client reports the application commit SHA when it can determine one. Local Git discovery runs in the background and never delays or fails application calls. Automatic branch discovery is off by default.
const raindrop = createRaindropTanstackAI({
writeKey: process.env.RAINDROP_WRITE_KEY,
appGit: {
commitSha: "0123456789abcdef0123456789abcdef01234567",
commitDirty: false,
branch: "main",
detectBranch: true,
sourceDirectory: "/path/to/application",
},
});
const withoutGit = createRaindropTanstackAI({
writeKey: process.env.RAINDROP_WRITE_KEY,
appGit: false,
});commitSha, commitDirty, and branch are explicit overrides. detectBranch opts into automatic branch lookup, sourceDirectory selects the application repository, and autoDetect: false disables automatic sources while retaining explicit values.
Captured content and size limits
Each model call's span records the full prompt (ai.prompt.messages: system prompts, then the user, assistant and tool messages with their tool-call ids, names, arguments and results), the tool calls the model requested (ai.response.toolCalls), and each tool span records its arguments and result. Pass captureContent: false to record identities and timings only.
maxTextFieldChars (default 1_000_000) caps every captured field. Oversized text is cut at the leaf and marked with ...[truncated by raindrop]; the JSON stays valid and ids and names are never cut. A prompt that does not fit ends with a { "role": "raindrop", "truncated": true, "omittedMessages": n } record and the span carries ai.prompt.messages.truncated: true; tool arguments and results that were cut carry ai.toolCall.args.truncated / ai.toolCall.result.truncated. OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT lowers the cap for span attributes when it is stricter.
const raindrop = createRaindropTanstackAI({
writeKey: process.env.RAINDROP_WRITE_KEY,
maxTextFieldChars: 200_000,
});Tool catalog capture
Every model call's span records the tools the engine handed the adapter for that call as ai.prompt.tools (TanStack inputSchemas are converted with convertSchemaToJsonSchema). Each tool is one JSON document in an OTLP string array: {"type":"function","name","description","inputSchema"} for function tools (the JSON Schema is recorded as given — properties, enums, required and per-field descriptions intact) or {"type":"provider-defined","id","name","args"} for provider-owned tools, which get no invented schema. A call without a visible tool list records no attribute; an explicit empty list records []. captureContent: false suppresses it with the rest of the prompt. Pass tools to record a different catalog instead (it replaces the inferred list; tools: [] records an empty catalog).
| Option | Type | Default | Description |
|---|---|---|---|
| tools | PromptToolsOverride | undefined | Overrides the tool catalog recorded as ai.prompt.tools on every model span. Use when the integration cannot see the tools the model was given. |
Per-call overrides
Override the user / conversation / event name on a single chat by setting context:
chat({
...,
context: { userId: "u-1", convoId: "c-1", eventName: "support_chat" },
});When convoId is not provided, the middleware falls back to TanStack's threadId, which is what makes multi-turn conversations land under one Workshop conversation.
