main without version tags.
Week of 2026-06-08 — Bitfrost (Python) 0.1.0
Python joins the family.bitfrost is a drop-in OpenTelemetry exporter for Python LLM apps — the Python counterpart to @voightxyz/vercel-ai. Same backend, same dashboard, different runtime; events from both land side-by-side under the same agent.
New
bitfrost0.1.0 —pip install bitfrost. One line (bitfrost.quickstart()) auto-detects and instruments openai / anthropic / litellm / smolagents. Built on the OpenTelemetry GenAI semantic conventions (v1.27 and v1.32+), so it works with the instrumentation libraries you already use. Get started →- Standalone-first. Capture to your terminal, a JSONL file, or SQLite with zero network calls — Voight is one optional backend, never a requirement. Ships five backends, four auto-instrument helpers, a rich CLI, an interactive TUI, and an offline local web dashboard (
bitfrost serve). - Private by default. Three privacy levels with in-process PII scrubbing (12 patterns + credit-card Luhn) applied before any event leaves the process.
Bitfrost is open source (MIT) on GitHub and works entirely on its own. Point it at Voight only when you want hosted dashboards and per-user spend.
Week of 2026-05-18 — Vercel AI SDK support, install wizard, GLM provider
A short recap of what shipped this week. Per-package version notes live in the sections below.New
@voightxyz/vercel-ai0.1.0 — first stable release of the Vercel AI SDK exporter. Register one OpenTelemetry exporter next to@vercel/oteland everystreamText/generateText/streamObject/generateObjectcall lands in your dashboard with accurate token counts, tool calls, and per-user attribution. Validated against thevercel/ai-chatbotreference app.@voightxyz/sdk initnow detects the Vercel AI SDK — runningnpx -y @voightxyz/sdk initin a project that usesaiwrites aninstrumentation.tsthat wires up the exporter automatically. Direct-wrapper projects (OpenAI / Anthropic only) get the same files as before. See the install wizard guide.- GLM (Z.ai / Zhipu) provider page — new GLM provider doc walks through using GLM models behind the OpenAI wrapper, with pricing and routing notes.
Updates
- One-line per-user attribution — both
@voightxyz/openaiand@voightxyz/anthropicnow accept atagsmap onwithTrace. Pass{ userId, plan, ... }once at the request boundary and every LLM call inside the block is stamped automatically. Lights up the dashboard’s Users sub-tab and per-user spend view. - Request-boundary trace grouping —
withTrace(fn, { routeTag })andlog(message, extra?)are now exported from both App SDKs. Group every LLM call from one request under a single trace card, interleaved with your own log lines. Mixing OpenAI and Anthropic calls in the same trace works without extra setup. @voightxyz/anthropicpeer range loosened to>=0.27.0— projects pinning older Anthropic SDK releases no longer hitERESOLVEon install. Runtime verified against0.29.2and0.96.0.
Fixes
- Vercel AI exporter token accuracy — outer wrapper spans are filtered out so token counts match the underlying provider’s billing, and
durationMsis rounded to an integer.
Already on the OpenAI or Anthropic wrapper? Adding per-user attribution is a one-line change — see the per-user spend guide.
@voightxyz/sdk— coding-agent hooks + library mode (autonomous bots)@voightxyz/openai— OpenAI Node SDK wrapper for production apps@voightxyz/anthropic— Anthropic Node SDK wrapper for production apps@voightxyz/vercel-ai— OpenTelemetry SpanExporter for the Vercel AI SDK
@voightxyz/vercel-ai changelog
0.1.1 — 2026-05-22
Dedup filter for wrapper-emitted spans. When@voightxyz/openai or @voightxyz/anthropic is wrapped with otel: true, every captured call would otherwise land twice in the Voight backend — once via the wrapper’s direct POST, once via this exporter. 0.1.1 teaches VoightExporter.export() to recognise the voight.source: 'wrapper' attribute the wrappers stamp on those spans, and skip them cleanly. Other OTel exporters in the same process (Langfuse, Datadog, Sentry) still see the spans — the dedup is scoped to the Voight-to-Voight loop.
Spans without that marker (the canonical streamText / generateText / streamObject / generateObject spans the Vercel AI SDK emits) are unaffected.
0.1.0 — 2026-05-21
First stable release.@voightxyz/vercel-ai is an OpenTelemetry SpanExporter for the Vercel AI SDK. Register it next to @vercel/otel, flip experimental_telemetry: { isEnabled: true } on your streamText / generateText / streamObject / generateObject calls, and every call lands in your Voight dashboard.
streamText/generateText/streamObject/generateObjectcapture (one event per LLM call — outer wrappers filtered out so token counts stay accurate)- OpenAI + Anthropic provider attribution (via
gen_ai.system/ai.model.provider) - Tool calls (normalised to
{id, name, arguments}JSON-string), token counts (input / output / cache_read / cache_creation), finish reason, streaming flag, sessionId - Per-user attribution via
experimental_telemetry.metadata— passing{ metadata: { userId, plan, ... } }activates the dashboard Users sub-tab + per-tag filter pills automatically - Three privacy levels (
'minimal'/'standard'/'full') sharing the same 12-pattern PII catalogue as the other wrappers - Coexists with other observability tools via OTel’s
MultiSpanProcessor
vercel/ai-chatbot reference app. Full setup at ai-apps/vercel-ai.
@voightxyz/openai changelog
0.1.7 — 2026-05-22
{ otel: true } opt-in — OpenTelemetry side-channel.
When set, every captured call is also emitted as an OpenTelemetry span with gen_ai.* semantic-convention attributes (plus the parallel ai.* namespace for Vercel cross-compatibility). The wrapper picks up whichever TracerProvider is registered in the host process, so you can wire it inside an OTel-mandated stack (Langfuse, Phoenix, Datadog, Sentry, @voightxyz/vercel-ai) without losing the direct ingestion to api.voight.xyz.
voight.openai.chat (or voight.openai.responses). Each span carries voight.source: 'wrapper' so @voightxyz/vercel-ai ≥ 0.1.1 deduplicates them automatically.
@opentelemetry/api is now an optional peer dependency. Default otel: false ships byte-identical behaviour to 0.1.6 — no extra install, no runtime cost.
0.1.6 — 2026-05-17
withTrace({ tags }) — per-user / per-tenant attribution.
withTrace now accepts a tags map alongside routeTag. Every wrapped LLM call inside the block gets stamped with metadata.tags automatically via AsyncLocalStorage. This is the one-line code change that lights up the dashboard’s Users sub-tab and powers per-user spend attribution.
0.1.5 — 2026-05-17
withTrace + log — request-boundary trace grouping.
New exports:
withTrace(fn, { routeTag })opens a logical trace; every wrapped LLM call inside the block is grouped under one trace card in the dashboard.log(message, extra?)emits a free-form event inside the current trace — interleaved with LLM calls in the timeline.
AsyncLocalStorage — no signature threading, no middleware required. Mixes cleanly with @voightxyz/anthropic (same backing store across both packages).
0.1.0 — 2026-05-15
Initial release. OpenAI Node SDK wrapper. Captures:- Chat Completions (
client.chat.completions.create) — non-streaming + streaming, tool calling - Responses API (
client.responses.create) — non-streaming + streaming, function calling, reasoning models - Token breakdown (input / output / cache reads / reasoning)
- Tool calls (full array per event)
- Latency, finish reason, error capture
@voightxyz/anthropic changelog
0.1.8 — 2026-05-22
{ otel: true } opt-in — OpenTelemetry side-channel.
Mirror of @voightxyz/openai@0.1.7 — same flag, same gen_ai.* + ai.* attribute shape, same voight.source: 'wrapper' dedup marker, same optional peer on @opentelemetry/api. Span name: voight.anthropic.messages. gen_ai.system resolves to 'anthropic'.
Default otel: false ships byte-identical behaviour to 0.1.7.
0.1.7 — 2026-05-17
Loosen@anthropic-ai/sdk peer-dependency from >=0.30.0 to >=0.27.0.
Real-world projects on older SDK versions hit ERESOLVE on install (Anthropic’s own customer-support-agent quickstart pins ^0.27.1; financial-data-analyst pinned ^0.29.0 — both rejected 0.1.6). The 0.30.0 floor was overly conservative — the wrapper consumes the SDK purely structurally (no type imports, only runtime field reads with defensive fallbacks), so older releases work fine.
Runtime verified against @anthropic-ai/sdk 0.29.2 and 0.96.0. 92/92 tests still green. No code changes — peer-dependency metadata only.
0.1.6 — 2026-05-17
withTrace({ tags }) — per-user / per-tenant attribution.
Mirror of @voightxyz/openai 0.1.6. Every wrapped messages.create call inside a withTrace block gets metadata.tags stamped automatically. Powers the dashboard’s Users sub-tab and per-user spend attribution.
0.1.5 — 2026-05-17
withTrace + log — request-boundary trace grouping.
Mirror of @voightxyz/openai 0.1.5. Same async-context store under the hood — import withTrace from either package; mixing providers in one trace works without setup.
0.1.0 — 2026-05-15
Initial release. Anthropic Node SDK wrapper. Captures:messages.create— non-streaming + streaming, tool use- Token breakdown (input / output / cache reads / cache creations)
- Path-A cache pricing (1.25× creation, 0.10× read applied server-side)
- Tool calls (flattened to
{ id, name, arguments }matching the OpenAI wrapper) - Latency, stop reason, error capture
@voightxyz/sdk changelog
0.6.5 — 2026-05-21
init wizard now detects the Vercel AI SDK.
If your package.json lists ai (Vercel AI SDK), the wizard takes a new third path: instead of writing src/lib/voight.ts with wrapped clients, it writes an instrumentation.ts that registers @voightxyz/vercel-ai with @vercel/otel. The Vercel AI SDK emits OpenTelemetry spans natively, so every streamText / generateText / streamObject / generateObject call carrying experimental_telemetry: { isEnabled: true } lands in your Voight dashboard with the same shape as direct-wrapper events.
Mixed projects (both ai and a direct provider in deps) take the Vercel path with an explicit message — the OTel exporter covers every underlying provider via gen_ai.* semconv normalisation.
Strictly additive: zero edits to the setup flow (Claude Code / Cursor / Codex hooks) or to the direct-wrapper path. A project that has only openai or @anthropic-ai/sdk (no ai) gets exactly the same files the 0.6.4 wizard produced — verified byte-for-byte via the registry-level smoke test before @latest promotion.
Same install command (npx -y @voightxyz/sdk init), same prompts (privacy + key + agent), framework-aware usage snippet, pm-tailored install command (pnpm add @voightxyz/vercel-ai @vercel/otel for the Vercel path).
0.6.4 — 2026-05-17
Newinit sub-command — scaffold Voight into a production app with one wizard.
For projects that already use the OpenAI or Anthropic Node SDK in production, init automates the install:
- Reads
package.jsonand detectsopenaiand/or@anthropic-ai/sdkalready in your deps. Aborts cleanly if neither is present. - Detects your package manager (pnpm / yarn / bun / npm) and your framework (Next.js or vanilla) to tailor the install command + usage snippet at the end.
- Prompts for privacy level (Standard recommended for customer-facing apps), Voight API key, and agent name.
- Validates the key against
api.voight.xyzbefore writing anything — typo’d keys get caught now instead of in production. - Generates
src/lib/voight.tswith the wrapped clients for the providers it detected, plus a header comment explaining how to adjust if your provider keys come from AWS Secrets Manager / Vault / Doppler instead of env vars. - Appends
VOIGHT_KEYto.env.local. Provider keys (OPENAI_API_KEY,ANTHROPIC_API_KEY) are never asked for — they belong to your app, the Voight wrapper never sees them. - Prints the right install command for your package manager + a usage snippet (Next.js Route Handler or Express, depending on what’s in your deps).
Safety guarantees
init lives in a new file src/init.ts with zero edits to setup.ts, hook.ts, or any other module. It never touches ~/.claude, ~/.cursor, or ~/.codex — only writes inside process.cwd(). Users of setup get byte-identical behaviour to 0.6.3; 256 tests green (was 214 + 42 new for init).
If you’d rather wire things up manually (no wizard), the package pages for OpenAI and Anthropic walk through the same install in three commands.
0.6.3 — 2026-05-14
Fix: Codex plugin install lands in the right cache dir + valid auth enum. Two last-mile Codex setup bugs. The plugin now installs into the location Codex actually loads from, and the authentication value matches Codex’s accepted enum so the wrapper no longer rejects it at startup.0.6.2 — 2026-05-14
Fix: install the SDK locally so hooks fire inside the Codex sandbox. Codex runs hooks inside a sandboxed environment that can’t reach globally-installed packages. Setup now drops the SDK into the project so the hook script resolves correctly on first run.0.6.1 — 2026-05-14
Fix:VOIGHT_SOURCE disambiguates Codex from Claude Code.
Both adapters share a hook entry point. The wrapper now sets VOIGHT_SOURCE so events route through the correct mapper instead of being misattributed.
0.6.0 — 2026-05-14
Codex support (verified target). Voight now wires into Codex the same way it wires into Claude Code and Cursor — onesetup command drops a local marketplace plugin that registers the hooks. Events show up in the live timeline with the same shape as other targets. See the quickstart for the install steps.
0.5.2 — 2026-05-14
Fix: route Cursor response and thought text through metadata. Cursor’s response and reasoning fields are now carried inmetadata instead of top-level event fields. The dashboard masks them by default with the same eye-toggle reveal used for Claude Code transcripts.
0.5.1 — 2026-05-14
Fix: normalise Cursormodel: 'default' to cursor-auto.
Cursor reports default for its auto-routing mode, which doesn’t tell you which model actually ran the turn. The SDK now rewrites it to cursor-auto so the dashboard’s model column is honest about what happened.
0.5.0 — 2026-05-14
Cursor support + framework-agnostic setup. Voight is no longer Claude-Code-only. Highlights:- Cursor adapter —
setupwires Cursor’shooks.json+ wrapper script, captures 5 extended hook events, and ships prompts and outcomes in the reasoning payload so the timeline renders Cursor turns end-to-end - Auto-detect the coding agent — run
setupwith no--targetflag and the CLI picks Claude Code, Cursor, or Codex based on your environment frameworkNamehelper — installer and runtime messages now reflect whichever agent you’re wiring intraceIdlifted into metadata — every event carries the trace ID the dashboard groups by, regardless of source- Apache-2.0 — the SDK is now Apache-2.0 licensed (was MIT). README rewritten to drop Claude-only framing
0.4.2 — 2026-05-10
Fix: explicit--privacy=N example in non-TTY welcome menu.
After 0.4.1 shipped, an alpha tester’s friend tried to install via Claude Code chat and the AI agent reading the wizard output didn’t know how to chain commands. The welcome menu now includes:
0.4.1 — 2026-05-08
3-step progressive flow for non-TTY (Claude Code chat). The 0.4.0 wizard relied on readline. Inside Claude Code chat (or any non-TTY shell) it silently defaulted tostandard privacy, never showed the welcome menu, and gave users no way to choose. 0.4.1 reshapes the non-TTY path:
- Step 1 — print welcome + privacy menu, exit
- Step 2 — accept
--privacy=N, print API key instructions, exit - Step 3 — accept both
--privacyand--key, write settings.json, show done message
settings.json on most modern versions.
0.4.0 — 2026-05-08
3-level privacy capture + local PII scrubbing. The biggest release since the SDK was first published. New capabilities:- Three privacy levels picked at install (Minimal / Standard / Full), via the setup wizard or
VOIGHT_PRIVACYenv var scrubPii()— 12 PII patterns + Luhn-validated credit cards, run on every string in every event under Standard mode, before the SDK transmits anythingapplyPrivacy(payload, level)— single integration point inhook.ts, allowlist-based for Minimal (forward-compat), deep-scrub for Standard- Per-event
metadata.privacyLevelstamp — every event ships with its level chip so the dashboard can audit retroactively - 77 new unit tests (61 → 138 SDK suite)
- E2E verified against the actual subprocess flow + wire capture, not just unit mocks
0.3.10 — 2026-05-06
Fix: match real Claude Code rejection phrasing in denial detector. The 0.3.9 denial-detection patterns were synthetic. 0.3.10 corrects them against captured rejection logs. Architectural caveat: PostToolUse doesn’t fire on user_rejected — that path is dead code in production. We’re sitting on this until we can capture the right hook flow.0.3.9 — 2026-05-06
Permission-denial classification (5 patterns). Added a denial classifier that promotes failed tool calls to a distinctdenial type when the failure shape matches a known pattern (user rejected, settings blocked, sandbox denied, requires approval, hook blocked). The dashboard renders these with a DENIED badge separate from real runtime errors.
Post-mortem: shipped against invented patterns. See architectural caveat above.
0.3.8 — 2026-05-05
Git context capture. Every event now carriesmetadata.git = { branch, sha, shortSha, remote, dirty } when running inside a git repo. Cached 30s per cwd to avoid spawning git on every event. Captures the exact code state that produced the trace.
0.3.7 — 2026-05-05
ScheduleWakeup recognition.
When the agent calls ScheduleWakeup, the SDK records the parameters. The next UserPromptSubmit that matches gets tagged promptSource: 'system' so the dashboard can distinguish autonomous loop ticks from real user prompts. Renders as a SYSTEM badge in the timeline.
0.3.5 — 2026-05-05
Agent response capture. The Stop hook now reads the local transcript backward to find the agent’s final text + stop reason + last thinking block. Surfaces them in the dashboard’s event detail panel (masked by default, eye toggle to reveal).0.3.4 — 2026-05-04
Marker file (.voight-agent-id) for rename-proof identity.
Server returns the agent’s CUID on every event response. SDK writes it to <cwd>/.voight-agent-id. Future events match by primary key — rename-proof, folder-rename-proof.
0.3.3 — 2026-05-04
Explicitmetadata.tokensBreakdown for exact pricing.
The flat tokens.input field conflates inputBase, cacheCreation, and cacheRead at the full rate. New breakdown field gives the backend exact prices (cache_read at 0.10×, cache_creation at 1.25×, input at 1.00×).
0.3.2 — 2026-05-04
ESM fs imports (fix silent fail on transcripts >4MB).0.3.1 — 2026-05-03
Lenient transcript matcher (handles edge cases in attribution).0.3.0 — 2026-05-03
Transcript-based token capture. The SDK now walks the local transcript JSONL on every PostToolUse, finds the assistant message that initiated the current tool, and pulls real token usage. Dedup via assistant message UUID — 1 message → N tools attributes once.Earlier versions
0.1.x and 0.2.x were the initial integration drafts. Not documented here — start at 0.3.0.Stay updated
- npm:
@voightxyz/sdk·@voightxyz/openai·@voightxyz/anthropic - GitHub:
voightxyz/voight-sdk·voightxyz/voight-openai·voightxyz/voight-anthropic(releases tagged) - Twitter: @voightxyz